JAXB使用CDATA编组解组
我正在尝试与JAXB进行编组。
我的输出就像
<![CDATA[<h1>kshitij</h1>]]> <h1>solanki</h1> <h1>1</h1>
但我需要输出像
<![CDATA[kshitij
]]> <![CDATA[solanki
]]>
我正在使用以下代码来执行此操作。 如果我取消注释代码,我会得到Property Binding Exception。 没有它我可以编译,但我没有得到确切的所需输出。
package com.ksh.templates; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import com.sun.xml.bind.marshaller.CharacterEscapeHandler; public class MainCDATA { public static void main(String args[]) { try { String name = "kshitij
"; String surname = "solanki
"; String id = "1
"; TestingCDATA cdata = new TestingCDATA(); cdata.setId(id); cdata.setName(name); cdata.setSurname(surname); JAXBContext jaxbContext = JAXBContext.newInstance(TestingCDATA.class); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { writer.write( ac, i, j ); } }); StringWriter stringWriter = new StringWriter(); marshaller.marshal(cdata, stringWriter); System.out.println(stringWriter.toString()); } catch (Exception e) { System.out.println(e); } } }
我的豆子喜欢
package com.ksh.templates; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import com.sun.xml.txw2.annotation.XmlCDATA; @XmlRootElement(name = "root") @XmlAccessorType(XmlAccessType.FIELD) public class TestingCDATA { @XmlElement @XmlJavaTypeAdapter(value = AdaptorCDATA.class) private String name; @XmlElement @XmlJavaTypeAdapter(value = AdaptorCDATA.class) private String surname; @XmlCDATA public String getName() { return name; } @XmlCDATA public void setName(String name) { this.name = name; } @XmlCDATA public String getSurname() { return surname; } @XmlCDATA public void setSurname(String surname) { this.surname = surname; } }
适配器类
public class AdaptorCDATA extends XmlAdapter { @Override public String marshal(String arg0) throws Exception { return ""; } @Override public String unmarshal(String arg0) throws Exception { return arg0; } }
您可以执行以下操作:
AdapterCDATA
package forum14193944; import javax.xml.bind.annotation.adapters.XmlAdapter; public class AdapterCDATA extends XmlAdapter { @Override public String marshal(String arg0) throws Exception { return ""; } @Override public String unmarshal(String arg0) throws Exception { return arg0; } }
根
@XmlJavaTypeAdapter
注释用于指定应使用XmlAdapter
。
package forum14193944; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlJavaTypeAdapter(AdapterCDATA.class) private String name; @XmlJavaTypeAdapter(AdapterCDATA.class) private String surname; @XmlJavaTypeAdapter(AdapterCDATA.class) private String id; }
演示
我必须在OutputStreamWriter
包装System.out
以获得所需的效果。 另请注意,设置CharacterEscapeHandler
意味着它负责该Marshaller
所有转义处理。
package forum14193944; import java.io.*; import javax.xml.bind.*; import com.sun.xml.bind.marshaller.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum14193944/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { @Override public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { writer.write(ac, i, j); } }); marshaller.marshal(root, new OutputStreamWriter(System.out)); } }
input.xml中/输出
kshitij]]> solanki]]>
请注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。
如果您使用MOXy作为JAXB(JSR-222)提供程序,那么您可以将@XmlCDATA
扩展用于您的用例。
根
@XmlCDATA
注释用于指示您希望包含在CDATA部分中的字段/属性的内容。 @XmlCDATA
注释可以与@XmlElement
结合使用。
package forum14193944; import javax.xml.bind.annotation.*; import org.eclipse.persistence.oxm.annotations.XmlCDATA; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlCDATA private String name; @XmlCDATA private String surname; @XmlCDATA private String id; }
jaxb.properties
要将MOXy用作JAXB提供程序,需要使用以下条目添加名为jaxb.properties
文件。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
演示
下面是一些演示代码,以certificate一切正常。
package forum14193944; import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/forum14193944/input.xml"); Root root = (Root) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } }
input.xml中/输出
下面是运行演示代码的输入和输出。
kshitij]]> solanki]]>
了解更多信息
很抱歉挖掘这个问题,并发布一个新的答案(我的代表还不够评论……)。 我遇到了同样的问题,我尝试了Blaise Doughan的答案,但是从我的测试中,要么它不能涵盖所有情况,要么我在某处做错了。
marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { @Override public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { writer.write(ac, i, j); } });
marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { @Override public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException { writer.write(ac, i, j); } });
从我的测试中,无论您是在属性上使用@XmlJavaTypeAdapter(AdapterCDATA.class)
注释,此代码都会删除所有转义。
为了解决这个问题,我实现了以下CharacterEscapeHandler
:
公共类CDataAwareUtfEncodedXmlCharacterEscapeHandler实现了CharacterEscapeHandler { private static final char [] cDataPrefix =“<![CDATA [”。toCharArray(); private static final char [] cDataSuffix =“]]>”。toCharArray(); public static final CDataAwareUtfEncodedXmlCharacterEscapeHandler instance = new CDataAwareUtfEncodedXmlCharacterEscapeHandler(); private CDataAwareUtfEncodedXmlCharacterEscapeHandler(){ } @覆盖 public void escape(char [] ch,int start,int length,boolean isAttVal,Writer out)throws IOException { boolean isCData = length> cDataPrefix.length + cDataSuffix.length; if(isCData){ for(int i = 0,j = start; i= 0; - i, - j){ if(cDataSuffix [i]!= ch [j]){ isCData = false; 打破; } } } } if(isCData){ out.write(ch,start,length); } else { MinimumEscapeHandler.theInstance.escape(ch,start,length,isAttVal,out); } } }
如果您的编码不是UTF *,您可能不想调用MinimumEscapeHandler,而是调用NioEscapeHandler甚至是DumbEscapeHandler。
com.sun.internal不适用于play2,但这有效
private static String marshal(YOurCLass xml){ try{ StringWriter stringWritter = new StringWriter(); Marshaller marshaller = JAXBContext.newInstance(YourCLass.class).createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-8859-1"); marshaller.marshal(xml, stringWritter); return stringWritter.toString().replaceAll("<", "<").replaceAll(">", ">"); } catch(JAXBException e){ throw new RuntimeException(e); } }
@Test public void t() throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); Root root = new Root(); root.name = "Jorge & Mary
"; marshaller.marshal(root, System.out); } @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public static class Root { @XmlCDATA private String name; } /* WHAT I SEE IN THE CONSOLE * <p>Jorge & Mary</p> */
我登陆这个页面试图找到类似问题的解决方案,我找到了解决这个问题的另一种方法。 解决此问题的一种方法是将XML作为SAX2事件发送到处理程序,然后在处理程序中编写逻辑以将CDATA标记添加到XML。 此方法不需要添加任何注释。 在从XSD生成要编组的类的场景中很有用。
假设您在从XSD生成的类中有一个字符串字段,该字段将被编组,并且字符串字段包含要放在CDATA标记内的特殊字符。
@XmlRootElement public class TestingCDATA{ public String xmlContent; }
我们将首先搜索一个合适的类,其方法可以在我们的内容处理程序中被覆盖。 其中一个类是在com.sun.xml.txw2.output包中找到的XMLWriter,它在jdk 1.7和1.8中可用。
import com.sun.xml.txw2.output.XMLWriter; import org.xml.sax.SAXException; import java.io.IOException; import java.io.Writer; import java.util.regex.Pattern; public class CDATAContentHandler extends XMLWriter { public CDATAContentHandler(Writer writer, String encoding) throws IOException { super(writer, encoding); } // see http://www.w3.org/TR/xml/#syntax private static final Pattern XML_CHARS = Pattern.compile("[<>&]"); public void characters(char[] ch, int start, int length) throws SAXException { boolean useCData = XML_CHARS.matcher(new String(ch, start, length)).find(); if (useCData) { super.startCDATA(); } super.characters(ch, start, length); if (useCData) { super.endCDATA(); } } }
我们重写了字符方法,使用正则表达式来检查是否包含任何特殊字符。 如果找到它们,那么我们在它们周围放置CDATA标签。 在这种情况下,XMLWriter负责添加CDATA标记。
我们将使用以下代码进行封送处理:
public String addCDATAToXML(TestingCDATA request) throws FormatException { try { JAXBContext jaxbContext = JAXBContext.newInstance(TestingCDATA.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); StringWriter sw = new StringWriter(); CDATAContentHandler cDataContentHandler = new CDATAContentHandler(sw, "UTF-8"); jaxbMarshaller.marshal(request, cDataContentHandler); return sw.toString(); } catch (JAXBException | IOException e) { throw new FormatException("Unable to add CDATA for request", e); } }
如果我们传递一个请求被编组,如下所述,这将封送对象并返回XML。
TestingCDATA request=new TestingCDATA(); request.xmlContent=""; System.out.println(addCDATAToXML(request)); // Would return the following String Output- ]]>
- 在服务器端为servlet JSP MVC网站运行定期任务
- java.util.MissingResourceException:找不到基本名称javax.servlet.LocalStrings的bundle,locale es_ES
- 带有RESTful JSON服务,HTML5和jQuery ajax的Java Web框架
- 使用beanshell更新Jmeter变量
- 如何检查哪些JTextField为空并告知用户有关它们的信息?
- 使用Java将BinHex文件转换为普通文件
- 多重inheritance和类对象
- 使用ant将jsps预编译为Jetty8的类
- 使用SunMSCAPI签署文档并禁止“输入PIN”对话框