代码之家  ›  专栏  ›  技术社区  ›  luthier

使用woodstox解析xml时保持实体不变

  •  0
  • luthier  · 技术社区  · 5 年前

    我使用woodstox处理包含一些实体的xml(尤其是 > )在其中一个节点的值中。举个极端的例子,它是这样的:

    <parent>&nbsp; &lt; &nbsp; &gt; &amp; &quot; &apos; &nbsp;</parent>

    我尝试了很多不同的配置选项 wstxinputfactory工厂 ( IS_REPLACING_ENTITY_REFERENCES , P_TREAT_CHAR_REFS_AS_ENTS , P_CUSTOM_INTERNAL_ENTITIES ……) WSTXOUTPUTFACTORY公司 ,但无论我尝试什么,输出始终是这样的:

    <parent>nbsp; &lt; nbsp; > &amp; " ' nbsp;</parent>

    ( &GT; 转换为 > , &lt; 保持不变, &nbsp; 失去了 & ……)

    我正在用 XML事件读取器 创建与

    XMLEventReader reader = wstxInputFactory.createXMLEventReader(new StringReader(fulltext));

    在配置 wstxinputfactory工厂 .

    有什么方法可以将woodstox配置为只忽略所有实体并输出与输入字符串中完全相同的文本吗?

    0 回复  |  直到 5 年前
        1
  •  0
  •   StaxMan    5 年前

    首先,您需要包含实际的代码,因为“输出总是这样”如果不准确地解释如何输出解析的内容就毫无意义:您可能正在打印事件、使用某些库,或者可能正在使用Woodstox流或事件编写器。

    第二:少量预定义实体之间的xml存在差异( lt , gt , apos , quot , amp ,以及任意用户定义的实体,如 nbsp 就在这里。前者可以按原样使用,它们已经被定义;后者只有在DTD中定义它们时才存在。

    对这两个组的处理也不同;前者无论如何都会被扩展,这是通过xml规范实现的。后者将被解析(除非禁用解析),然后被扩展——或者如果未定义异常将被抛出。 您也可以指定自定义解析器,如另一个答案所述;但这将仅用于自定义实体(这里, &nbsp; )

    最后,最好不要解释你在做什么,而要解释你在努力实现什么。这将有助于提出比“我该怎么做”这类具体问题更好的建议,而这些问题可能不是解决问题的方法。

    至于Woodstox的配置,也许这篇博文:

    https://medium.com/@cowtowncoder/configuring-woodstox-xml-parser-woodstox-specific-properties-1ce5030a5173

    将有帮助(以及本系列中的另外两个)--它涵盖了现有的配置设置。

        2
  •  0
  •   Iñaki Ibarrola Atxa    5 年前

    基本的五个XML实体(quot、amp、apos、lt、gt)将始终被处理。据我所知,没有办法用sax找到它们的来源。

    对于其他实体,可以手动处理它们。您可以捕获事件,直到元素结束并连接值:

        XMLInputFactory factory = WstxInputFactory.newInstance();
        factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
        XMLEventReader xmlr = factory.createXMLEventReader(
                this.getClass().getResourceAsStream(xmlFileName));
    
        String value = "";
        while (xmlr.hasNext()) {
            XMLEvent event = xmlr.nextEvent();
            if (event.isCharacters()) {
                value += event.asCharacters().getData();
            }
            if (event.isEntityReference()) {
                value += "&" + ((EntityReference) event).getName() + ";";
            }
            if (event.isEndElement()) {
                // Assign it to the right variable
                System.out.println(value);
                value = "";
            }
        }
    

    对于您的示例输入:

    <parent>&nbsp; &lt; &nbsp; &gt; &amp; &quot; &apos; &nbsp;</parent>
    

    输出为:

    &nbsp; < &nbsp; > & " ' &nbsp;
    

    否则,如果要转换所有实体,则可以使用自定义 XmlResolver 对于未声明的实体:

    public class NaiveHtmlEntityResolver implements XMLResolver {
    
        private static final Map<String, String> ENTITIES = new HashMap<>();
    
        static {
            ENTITIES.put("nbsp", " ");
            ENTITIES.put("apos", "'");
            ENTITIES.put("quot", "\"");
            // and so on
        }
    
        @Override
        public Object resolveEntity(String publicID,
                String systemID,
                String baseURI,
                String namespace) throws XMLStreamException {
            if (publicID == null && systemID == null) {
                return ENTITIES.get(namespace);
            }
            return null;
        }
    }
    

    然后告诉Woodstox将其用于未声明的实体:

        factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, new NaiveHtmlEntityResolver());