【问题标题】:Java XML parsing - merging the output of xi:includeJava XML 解析 - 合并 xi:include 的输出
【发布时间】:2016-08-06 00:26:53
【问题描述】:

我有一个包含以下内容的 XML 文件:

<contexts>
    <context name="a">
        <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/>
        <other_stuff/>
    </context>
    <context name="b">
        <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/>
        <other_stuff/>
    </context>
</contexts>

...以及上面 XInclude 引用的reuse.xml,其中包含如下内容:

<good_stuff/><!-- and a bunch of complex stuff ->

我正在尝试编写一些 Java 代码,它可以为每个上下文元素生成一些字符串输出(简单),但不是 xi:include 行,而是用包含文件的内容替换它,即给我一个“爆炸”每个上下文的字符串如下:

<context name="a">
    <good_stuff/><!-- and a bunch of complex stuff ->
    <other_stuff/>
</context>

而不是我现在得到的:

<context name="a">
    <xi:include xmlns:xi="http://www.w3.org/2003/XInclude" href="reuse.xml"/> 
    <other_stuff/>
</context>

希望我已经清楚地解释了自己,我不希望在我的输出中包含 xi:include 文本,而是应该替换它的另一个文件的内容。

我将解析器设置为 XInclude 和命名空间感知:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setXIncludeAware(true);

...

然后获取我想要的类型的子节点(在这种情况下,类型给了我上下文)。

NodeList result = doc.getElementsByTagName(type).item(0).getChildNodes();

但是当我对此进行迭代,并使用以下内容将每个元素传递给 StringWriter 时,它并没有替换 xi:include;

StringWriter sw = new StringWriter();
Transformer serializer = TransformerFactory.newInstance().newTransformer();
serializer.setOutputProperty(OutputKeys.INDENT, "no");
serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
serializer.setOutputProperty(OutputKeys.STANDALONE, "yes");
serializer.transform(new DOMSource(element), new StreamResult(sw));
String result = sw.toString();

除了使用字符串操作来替换 xi:include 我自己之外,还有其他方法可以使用 JDK 7/8 内置 XML 解析器吗?

感谢您的帮助!

【问题讨论】:

  • 我会自己替换 xi:include,但我认为不需要进行字符串操作。但是可能提供了一个 xi:include 设施,我不知道。
  • 我怀疑这是一个命名空间问题,W3C XInclude 命名空间是http://www.w3.org/2001/XInclude 而不是http://www.w3.org/2003/XInclude

标签: java xml parsing dom


【解决方案1】:

当我更改要使用的 XML 时,我认为您为 XInclude 引用使用了错误的命名空间

<?xml version="1.0" encoding="UTF-8"?>
<contexts>
    <context name="a">
        <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
        <other_stuff/>
    </context>
    <context name="b">
        <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="reuse.xml"/>
        <other_stuff/>
    </context>
</contexts>

使用 W3C XInclude 规范中定义的命名空间 http://www.w3.org/2001/XInclude https://www.w3.org/TR/xinclude/#syntax,并使用示例 XML 文档

<?xml version="1.0" encoding="UTF-8"?>
<good_stuff/>

然后Java代码输出例如

<context name="a">
        <good_stuff xml:base="reuse.xml"/>
        <other_stuff/>
    </context>
<context name="b">
        <good_stuff xml:base="reuse.xml"/>
        <other_stuff/>
    </context>

使用默认转换器输出context 元素时:

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.setXIncludeAware(true);

    DocumentBuilder docBuilder = factory.newDocumentBuilder();

    Document doc = docBuilder.parse("file1.xml");

    NodeList contextElements = doc.getElementsByTagName("context");

    for (int i = 0, l = contextElements.getLength(); i < l; i++) {
        Node element = contextElements.item(i);
        StringWriter sw = new StringWriter();
        Transformer serializer = TransformerFactory.newInstance().newTransformer();
        serializer.setOutputProperty(OutputKeys.INDENT, "no");
        serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        serializer.setOutputProperty(OutputKeys.STANDALONE, "yes");

        serializer.transform(new DOMSource(element), new StreamResult(sw));
        String result = sw.toString();
        System.out.println(result);
    }

【讨论】:

  • 感谢您的建议。不幸的是,修改 XML 不在我的控制范围内,但也许我可以在解析之前从 2003 年到 2001 年进行快速搜索和替换。现在,我选择解析两个文档并采用节点,并在找到要替换的 xi:include 时使用深层副本克隆它。谢谢大家!
  • 您应该通知 XML 的提供者命名空间是错误的。几年前,关于 XInclude 命名空间 URI 存在一些混淆。首先它被定义为http://www.w3.org/2001/XInclude。然后它被改为http://www.w3.org/2003/XInclude,稍后又恢复为http://www.w3.org/2001/XInclude。见w3.org/TR/2004/CR-xinclude-20040413
猜你喜欢
  • 2012-11-13
  • 1970-01-01
  • 2016-07-13
  • 2016-03-19
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
  • 2012-04-29
  • 1970-01-01
相关资源
最近更新 更多