我正在使用JAXB将Java对象转换为XML。我需要在输出XML中将撇号(')字符转义为'。默认情况下,JAXB不会转义撇号字符。我通过实现CharacterEscapeHandler
了解了如何实现自定义转义处理程序。但是,我意识到这个类不包含在Java 1.7中。我在哪里可以获得包含这类的最新库?这个下载的JAXB库中的类是否会与Java 1.7中的JAXB类冲突?
提前致谢。
答案 0 :(得分:0)
为了不依赖于JRE的其他版本/实现中不可用的内部类,您应该编写自己的ContentHandler
(SAX)或XMLStreamWriter
(StAX)。这样你就可以完全控制输出。
这是一个例子。它显示了JAXB如何正常输出XML以及如何使用ContentHandler
自行完成。这很简单,例如性能不是很好,没有命名空间支持。您可能希望编写更好的escape()
方法版本。您也可能希望将输出写入文件,而不是控制台。
public class Main {
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(MyData.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(new MyData("Test < ' \" & >", "Test < ' \" & >"), System.out);
System.out.println();
marshaller.marshal(new MyData("Test < ' \" & >", "Test < ' \" & >"), new MyContentHandler());
}
}
@XmlRootElement
class MyData {
@XmlAttribute private String name;
@XmlElement private String desc;
public MyData() {}
public MyData(String name, String desc) { this.name = name; this.desc = desc; }
}
class MyContentHandler implements ContentHandler {
@Override
public void setDocumentLocator(Locator locator) {
// Nothing to do
}
@Override
public void startDocument() throws SAXException {
System.out.print("<?xml version=\"1.0\" encoding=\"" + Charset.defaultCharset() + "\" standalone=\"yes\"?>");
}
@Override
public void endDocument() throws SAXException {
// Nothing to do
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException {
throw new UnsupportedOperationException();
}
@Override
public void endPrefixMapping(String prefix) throws SAXException {
throw new UnsupportedOperationException();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
System.out.print('<' + localName);
for (int i = 0; i < atts.getLength(); i++)
System.out.print(' ' + atts.getLocalName(i) + "=\"" + escape(atts.getValue(i)) + '"');
System.out.print('>');
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("</" + localName + ">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.print(escape(new String(ch, start, length)));
}
private static String escape(String text) {
return text.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("'", "'")
.replace("\"", """);
}
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
throw new UnsupportedOperationException();
}
@Override
public void processingInstruction(String target, String data) throws SAXException {
throw new UnsupportedOperationException();
}
@Override
public void skippedEntity(String name) throws SAXException {
throw new UnsupportedOperationException();
}
}
输出
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><myData name="Test < ' " & >"><desc>Test < ' " & ></desc></myData>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><myData name="Test < ' " & >"><desc>Test < ' " & ></desc></myData>
答案 1 :(得分:0)
尽管我喜欢Andreas的回答,但我不喜欢从头开始编写自己的XmlStreamWriter
。我建议使用Woodstox中的实现并提供自己的EscapingWriterFactory
。像这样:
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
的示例。