【问题标题】:Make JAXB escape apostrophe使 JAXB 转义撇号
【发布时间】:2016-03-23 15:26:51
【问题描述】:

我正在使用 JAXB 将 Java 对象转换为 XML。我需要在输出 XML 中将撇号 (') 字符转义为 '。默认情况下,JAXB 不会转义撇号字符。我通过实现CharacterEscapeHandler 了解了如何实现自定义转义处理程序。但是,我意识到这个类不包含在 Java 1.7 中。我在哪里可以获得包含此类的最新库?这个下载的 JAXB 库中的类会与 Java 1.7 中的 JAXB 类冲突吗?

【问题讨论】:

  • 只是好奇:为什么?生成的 XML 无效吗?
  • 通常不需要转义撇号。但是我们有一个要求,它必须被转义。所以我需要弄清楚如何做到这一点。

标签: java xml jaxb escaping


【解决方案1】:

虽然我喜欢 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 的示例。

【讨论】:

    【解决方案2】:

    为了不依赖在 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("&", "&amp;")
                       .replace("<", "&lt;")
                       .replace(">", "&gt;")
                       .replace("'", "&apos;")
                       .replace("\"", "&quot;");
        }
        @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 &lt; ' &quot; &amp; &gt;"><desc>Test &lt; ' " &amp; &gt;</desc></myData>
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><myData name="Test &lt; &apos; &quot; &amp; &gt;"><desc>Test &lt; &apos; &quot; &amp; &gt;</desc></myData>
    

    【讨论】:

      猜你喜欢
      • 2013-07-13
      • 2011-09-23
      • 2015-08-27
      • 2018-08-26
      • 2018-09-21
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多