让 JAXB 转义撇号
Make JAXB escape apostrophe
我正在使用 JAXB 将 Java 对象转换为 XML。我需要在输出 XML 中将撇号 ('
) 字符转义为 '
。默认情况下,JAXB 不会转义撇号字符。我通过实现 CharacterEscapeHandler
了解了如何实现自定义转义处理程序。但是,我意识到 class 不包含在 Java 1.7 中。我在哪里可以获得包含 class 的最新库?此下载的 JAXB 库中的 classes 是否会与 Java 1.7 中的 JAXB classes 冲突?
为了不依赖于 JRE 的其他 versions/implementations 中不可用的内部 类,您应该编写自己的 ContentHandler
(SAX) or 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>
虽然我喜欢 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);
如何编写 EscapingWriter
的示例可以在 CharacterEscapingTest 中看到。
我正在使用 JAXB 将 Java 对象转换为 XML。我需要在输出 XML 中将撇号 ('
) 字符转义为 '
。默认情况下,JAXB 不会转义撇号字符。我通过实现 CharacterEscapeHandler
了解了如何实现自定义转义处理程序。但是,我意识到 class 不包含在 Java 1.7 中。我在哪里可以获得包含 class 的最新库?此下载的 JAXB 库中的 classes 是否会与 Java 1.7 中的 JAXB classes 冲突?
为了不依赖于 JRE 的其他 versions/implementations 中不可用的内部 类,您应该编写自己的 ContentHandler
(SAX) or 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>
虽然我喜欢 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);
如何编写 EscapingWriter
的示例可以在 CharacterEscapingTest 中看到。