4

我正在使用 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;失去&......)

我正在使用创建的XMLEventReader读取 XML

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

配置WstxInputFactory之后。

有没有办法将 Woodstox 配置为忽略所有实体并完全按照输入字符串中的内容输出文本?

4

2 回答 2

0

将始终处理基本的五个 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());
于 2019-02-13T21:57:32.060 回答
0

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

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

两组的处理方式也不同;无论如何,前者总是会被扩展,这是 XML 规范的。后者将被解析(除非禁用解析),然后展开 - 或者如果未定义异常将被抛出。您还可以指定自定义解析器作为其他答案的提及;但这只会用于自定义实体(此处为&nbsp;)。

最后,最好不要解释你正在做什么,而是解释你想要达到的目标。这将有助于提出比“我如何做 X”的具体问题更好的建议,这可能不是解决方法。

至于 Woodstox 的配置,也许是这个博客条目:

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

将有所帮助(以及该系列中的其他 2 个)——它涵盖了现有的配置设置。

于 2019-02-14T17:10:22.057 回答