使用Woodstox解析XML时保持实体不变

时间:2019-02-13 15:41:30

标签: java xml stax woodstox

我正在使用Woodstox处理XML,该XML包含一个节点的值中的某些实体(最著名的是S state = getOneState())。举一个极端的例子,它是这样的:

>

我为 WstxInputFactory <parent>&nbsp; &lt; &nbsp; &gt; &amp; &quot; &apos; &nbsp;</parent>IS_REPLACING_ENTITY_REFERENCESP_TREAT_CHAR_REFS_AS_ENTS ...)和 WstxOutputFactory < / strong>,但是无论我如何尝试,输出始终都是这样的:

P_CUSTOM_INTERNAL_ENTITIES

({<parent>nbsp; &lt; nbsp; > &amp; " ' nbsp;</parent>被转换为&gt;>保持不变,&lt;失去了&nbsp; ...)

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

&

配置 WstxInputFactory 之后。

是否可以将Woodstox配置为仅忽略所有实体并完全按照输入字符串中的文本输出文本?

2 个答案:

答案 0 :(得分: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());

答案 1 :(得分:0)

首先,您需要包括实际代码,因为在没有确切说明如何输出已解析的内容的情况下,“输出始终是这样的”是没有意义的:您可能正在打印事件,正在使用某些库,或者可能正在使用Woodstox流或事件编写器。

第二个:少量的预定义实体(ltgtaposquotamp)之间的XML有所不同,和任意的用户定义实体,例如nbsp。以前您可以按原样使用,它们已经定义;只有在DTD中定义它们时,后者才存在。

两组的处理方式也不同;前者无论如何都将始终被扩展,这是XML规范。稍后将解决(除非禁用分辨率),然后再进行扩展-否则将引发异常。 您还可以指定自定义解析器,如其他答案所述。但这仅用于自定义实体(此处为&nbsp;)。

最后,最好不要解释自己在做什么和尝试实现什么。相对于“我怎么做X”的具体问题(可能不是解决方法),这将有助于更好地提出建议。

关于Woodstox的配置,也许这​​个博客条目:

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

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