如何使用带有Xinclude的xpointer来引用元素

时间:2013-05-15 10:50:13

标签: xml xinclude xpointer

我想合并两个具有相同结构的XML文件来制作一个。例如;

Test1.xml

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

<ns:Root
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="urn:TestNamespace"
    xsi:schemaLocation="urn:Test.Namespace Test1.xsd"
    >
    <ns:element1 id="001">
       <ns:element2 id="001.1" order="1">
           <ns:element3 id="001.1.1" />
       </ns:element2>
       <ns:element2 id="001.2" order="2">
           <ns:element3 id="001.1.2" />
       </ns:element2>
    </ns:element1>
</ns:Root>

Test2.xml

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

<ns:Root
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="urn:TestNamespace"
    xsi:schemaLocation="urn:Test.Namespace Test1.xsd"
    >
    <ns:element1 id="999">
        <ns:element2 id="999.1" order="1">
            <ns:element3 id="999.1.1" />
        </ns:element2>
    </ns:element1>
</ns:Root>

创建

TestOutput.xml

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

<ns:Root
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="urn:TestNamespace"
    xsi:schemaLocation="urn:Test.Namespace Test1.xsd"
    >
    <ns:element1 id="001">
       <ns:element2 id="001.1" order="1">
           <ns:element3 id="001.1.1" />
       </ns:element2>
       <ns:element2 id="001.2" order="2">
           <ns:element3 id="001.1.2" />
       </ns:element2>
    </ns:element1>
    <ns:element1 id="999">
        <ns:element2 id="999.1" order="1">
            <ns:element3 id="999.1.1" />
        </ns:element2>
    </ns:element1>
</ns:Root>

即一个XML文件,其中包含每个元素的所有元素。

我在StackOverflow上找到了一个有用的问题,并提出了这个问题;

的merge.xml

<?xml version="1.0"?>

<ns:Root xmlns:xi="http://www.w3.org/2003/XInclude"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="urn:TestNamespace">

    <xi:include href="Test1.xml" parse="xml" xpointer="element(//ns:Root/ns:element1)" />  

    <xi:include href="Test2.xml" parse="xml" xpointer="element(//ns:Root/ns:element1)" />

</ns:Root>

我通过这样做运行(我需要使用xmllint以便参与进入)

  

xmllint -xinclude Merge.xml

但这不起作用,它抱怨各种thiongs,似乎与xpointer有关。

parser error : warning: ChildSeq not starting by /1
Merge.xml:7: element include: XInclude error : XPointer evaluation failed: #element(//ns:Root/ns:element1)
Merge.xml:7: element include: XInclude error : could not load Test1.xml, and no fallback was found
parser error : warning: ChildSeq not starting by /1
Merge.xml:9: element include: XInclude error : XPointer evaluation failed: #element(//ns:Root/ns:element1)
Merge.xml:9: element include: XInclude error : could not load Test2.xml, and no fallback was found
<?xml version="1.0"?>
<ns:Root xmlns:xi="http://www.w3.org/2003/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns="urn:TestNamespace">

    <xi:include href="Test1.xml" parse="xml" xpointer="element(//ns:Root/ns:element1)"/>

    <xi:include href="Test2.xml" parse="xml" xpointer="element(//ns:Root/ns:element1)"/>

</ns:Root>

如果我省略了 Merge.xml 中的xpointer属性,那么我会得到一些合理的输出,但它除了包含我想要的元素之外还做了更多。

有人可以就xpointer的错误提供一些建议吗?

谢谢你的反对。

2 个答案:

答案 0 :(得分:3)

我已经涉足了这个问题,并在网上发现了大量的例子,这些例子表明我所做的是正确的。这是一个有效的版本...

<?xml version="1.0"?>

<Root xmlns:xi="http://www.w3.org/2003/XInclude"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="http://testurl.com/now">

    <xi:include href="Test1.xml" xpointer="xmlns(ns=http://testurl.com/now)xpointer(/ns:Root/ns:element1)" parse="xml" />
    <xi:include href="Test2.xml" xpointer="xpointer(//Root/element1)" parse="xml" />

</Root>

此示例使用具有名称空间的Test1.xml版本和不具有名称空间的Test2.xml。

输出现在看起来像这样......

<?xml version="1.0"?>
<Root xmlns:xi="http://www.w3.org/2003/XInclude" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns="http://testurl.com/now">

    <ns:element1 xmlns:ns="http://testurl.com/now" id="001">
        <ns:element2 id="001.1" order="1">
            <ns:element3 id="001.1.1"/>
        </ns:element2>
        <ns:element2 id="001.2" order="2">
            <ns:element3 id="001.1.2"/>
        </ns:element2>
    </ns:element1><ns:element1 xmlns:ns="http://testurl.com/now" id="003">
        <ns:element2 id="007.0" order="1">
            <ns:element3 id="007.1.1"/>
        </ns:element2>
    </ns:element1><ns:element1 xmlns:ns="http://testurl.com/now" id="002">
        <ns:element2 id="002.1" order="3">
            <ns:element3 id="002.1.1"/>
        </ns:element2>
        <ns:element2 id="002.2" order="4">
            <ns:element3 id="002.1.2"/>
        </ns:element2>
    </ns:element1>
    <element1 id="999">
        <element2 id="999.1" order="1">
            <element3 id="999.1.1"/>
        </element2>
    </element1>

</Root>

这当然是可以接受的,如果element1的打开和关闭之间的换行仍然存在,那就太好了

答案 1 :(得分:0)

这可以使用和不使用名称空间:

<?xml version="1.0"?>
<ns:Root xmlns:xi="http://www.w3.org/2003/XInclude"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ns="urn:TestNamespace">

    <xi:include href="Test1.xml" xpointer="xpointer(*/*)" />  
    <xi:include href="Test2.xml" xpointer="xpointer(*/*)" />

</ns:Root>

parse="xml"也是默认值。您不需要指定它。