我可以强制JAXB不转换成“进入”,例如,当编组到XML时?

我有一个使用JAXB编组为XML的Object。 一个元素包含一个包含引号(“)的String。生成的XML具有" where“存在的位置。

即使这通常是首选,我需要我的输出来匹配遗留系统。 如何强制JAXB不转换HTML实体?

感谢您的答复。 但是,我从未看到调用处理程序escape()。 你能看一看,看看我做错了什么吗? 谢谢!

 package org.dc.model; import java.io.IOException; import java.io.Writer; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.dc.generated.Shiporder; import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler; public class PleaseWork { public void prettyPlease() throws JAXBException { Shiporder shipOrder = new Shiporder(); shipOrder.setOrderid("Order's ID"); shipOrder.setOrderperson("The woman said, \"How ya doin & stuff?\""); JAXBContext context = JAXBContext.newInstance("org.dc.generated"); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CharacterEscapeHandler() { @Override public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { out.write("Called escape for characters = " + ch.toString()); } }); marshaller.marshal(shipOrder, System.out); } public static void main(String[] args) throws Exception { new PleaseWork().prettyPlease(); } } 

输出是这样的:

   The woman said, "How ya doin & stuff?"  

正如您所看到的,回调永远不会显示。 (一旦我调用了回调函数,我会担心它实际上会按照我想要的方式执行。)

解决我的队友发现:

 PrintWriter printWriter = new PrintWriter(new FileWriter(xmlFile)); DataWriter dataWriter = new DataWriter(printWriter, "UTF-8", DumbEscapeHandler.theInstance); marshaller.marshal(request, dataWriter); 

不是将xmlFile传递给marshal(),而是传递DataWriter,它知道编码和适当的转义处理程序(如果有的话)。

注意:由于DataWriter和DumbEscapeHandler都在com.sun.xml.internal.bind.marshaller包中,因此必须引导javac。

我刚把自定义处理程序作为这样的类:

 import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import com.sun.xml.bind.marshaller.CharacterEscapeHandler; public class XmlCharacterHandler implements CharacterEscapeHandler { public void escape(char[] buf, int start, int len, boolean isAttValue, Writer out) throws IOException { StringWriter buffer = new StringWriter(); for (int i = start; i < start + len; i++) { buffer.write(buf[i]); } String st = buffer.toString(); if (!st.contains("CDATA")) { st = buffer.toString().replace("&", "&").replace("<", "<") .replace(">", ">").replace("'", "'") .replace("\"", """); } out.write(st); System.out.println(st); } } 

在marshaller方法中只需调用:

 marshaller.setProperty(CharacterEscapeHandler.class.getName(), new XmlCharacterHandler()); 

它工作正常。

我一直在玩你的例子并调试JAXB代码。 它似乎是使用UTF-8编码的特定内容。 MarshallerImpl的escapeHandler属性似乎设置正确。 然而,它并没有在每种情况下使用。 如果我搜索了MarshallerImpl.createEscapeHandler()调用,我发现:

 public XmlOutput createWriter( OutputStream os, String encoding ) throws JAXBException { // UTF8XmlOutput does buffering on its own, and // otherwise createWriter(Writer) inserts a buffering, // so no point in doing a buffering here. if(encoding.equals("UTF-8")) { Encoded[] table = context.getUTF8NameTable(); final UTF8XmlOutput out; if(isFormattedOutput()) out = new IndentingUTF8XmlOutput(os,indent,table); else { if(c14nSupport) out = new C14nXmlOutput(os,table,context.c14nSupport); else out = new UTF8XmlOutput(os,table); } if(header!=null) out.setHeader(header); return out; } try { return createWriter( new OutputStreamWriter(os,getJavaEncoding(encoding)), encoding ); } catch( UnsupportedEncodingException e ) { throw new MarshalException( Messages.UNSUPPORTED_ENCODING.format(encoding), e ); } } 

请注意,在您的设置中,顶部(...equals("UTF-8")...)被考虑在内。 但是这个不采用escapeHandler 。 但是,如果将编码设置为任何其他,则调用此方法的底部( createWriter(OutputStream, String) ),并且此方法使用escapeHandler ,因此EH扮演其角色。 所以,添加……

  marshaller.setProperty(Marshaller.JAXB_ENCODING, "ASCII"); 

使您的自定义CharacterEscapeHandler被调用。 不太确定,但我猜这是JAXB中的一种错误。

@Elliot你可以使用它来使marshaller进入characterEscape函数。 它很奇怪但是如果你设置“ Unicode ”而不是“UTF-8”它就可以工作。 在设置CharacterEscapeHandler属性之前或之后添加此属性。

 marshaller.setProperty(Marshaller.JAXB_ENCODING, "Unicode"); 

但是,不能确定只是通过检查 IDE中的控制台 ,因为它应该显示取决于工作区编码。 最好还是从这样的文件中检查它:

 marshaller.marshal(shipOrder, new File("C:\\shipOrder.txt")); 

我想说最简单的方法是重写CharacterEscapeHandler

 marshaller.setProperty("com.sun.xml.bind.characterEscapeHandler", new CharacterEscapeHandler() { @Override public void escape(char[] ch, int start, int length, boolean isAttVal, Writer out) throws IOException { out.write(ch, start, length); } }); 

看起来Sun的JAXB实现是可能的 ,尽管我自己没有这样做。

阅读其他post后,这对我有用:

 javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(object); marshaller = jc.createMarshaller(); marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(CharacterEscapeHandler.class.getName(), new CustomCharacterEscapeHandler()); public static class CustomCharacterEscapeHandler implements CharacterEscapeHandler { /** * Escape characters inside the buffer and send the output to the Writer. * (prevent  to be converted <b> but still ok for a<5.) */ public void escape(char[] buf, int start, int len, boolean isAttValue, Writer out) throws IOException { if (buf != null){ StringBuilder sb = new StringBuilder(); for (int i = start; i < start + len; i++) { char ch = buf[i]; //by adding these, it prevent the problem happened when unmarshalling if (ch == '&') { sb.append("&"); continue; } if (ch == '"' && isAttValue) { sb.append("""); continue; } if (ch == '\'' && isAttValue) { sb.append("'"); continue; } // otherwise print normally sb.append(ch); } //Make corrections of unintended changes String st = sb.toString(); st = st.replace("&quot;", """) .replace("&lt;", "<") .replace("&gt;", ">") .replace("&apos;", "'") .replace("&amp;", "&"); out.write(st); } } } 

我发现同样的问题我在xmlWriter文件中使用xmlWriter修复了这个问题,有一个方法isEscapeText()和setEscapeTest默认为true如果你不想在

 JAXBContext jaxbContext = JAXBContext.newInstance(your class); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Create a filter that will remove the xmlns attribute NamespaceFilter outFilter = new NamespaceFilter(null, false); // Do some formatting, this is obviously optional and may effect // performance OutputFormat format = new OutputFormat(); format.setIndent(true); format.setNewlines(true); // Create a new org.dom4j.io.XMLWriter that will serve as the // ContentHandler for our filter. XMLWriter writer = new XMLWriter(new FileOutputStream(file), format); writer.setEscapeText(false); // <----------------- this line // Attach the writer to the filter outFilter.setContentHandler(writer); // marshalling marshaller.marshal(piaDto, outFilter); marshaller.marshal(piaDto, System.out); 

这改变了writer.setEscapeText(false); 解决了我的问题,希望这些变化对您有所帮助

有趣,但你可以尝试使用字符串

 Marshaller marshaller = jaxbContext.createMarshaller(); StringWriter sw = new StringWriter(); marshaller.marshal(data, sw); sw.toString(); 

至少对我而言,这并不是逃避引用

使用sun的Marshaller实现时最简单的方法是提供自己的CharacterEscapeEncoder实现,它不会逃避任何事情。

  Marshaller m = jcb.createMarshaller(); m.setProperty( "com.sun.xml.bind.marshaller.CharacterEscapeHandler", new NullCharacterEscapeHandler()); 

 public class NullCharacterEscapeHandler implements CharacterEscapeHandler { public NullCharacterEscapeHandler() { super(); } public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException { writer.write( ch, start, length ); } } 

由于某些原因,我没有时间找到它,它在设置时对我有用

 marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8"); 

与使用"UTF-8""Unicode"相反

我建议你尝试一下,正如@Javatar所说 ,检查他们使用以下方式转储到文件:

 marshaller.marshal(shipOrder, new File("")); 

并用一个体面的文本编辑器打开它,如记事本++

出于上述原因,我建议不要使用CharacterEscapeHandler (它是一个内部类)。 相反,您可以使用Woodstox并将自己的EscapingWriterFactory提供给XMLStreamWriter 。 就像是:

 XMLOutputFactory2 xmlOutputFactory = (XMLOutputFactory2)XMLOutputFactory.newFactory(); xmlOutputFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new EscapingWriterFactory() { @Override public Writer createEscapingWriterFor(Writer w, String enc) { return new EscapingWriter(w); } @Override public Writer createEscapingWriterFor(OutputStream out, String enc) throws UnsupportedEncodingException { return new EscapingWriter(new OutputStreamWriter(out, enc)); } }); marshaller.marshal(model, xmlOutputFactory.createXMLStreamWriter(out); 

在CharacterEscapingTest中可以看到如何编写EscapingWriter的示例。

Interesting Posts