8

我想将 2 个具有相同结构的 XML 文件合并为一个。例如;

测试1.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>

去创造

测试输出.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 上发现了一个有用的问题,并提出了这个问题;

合并.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

但这不起作用,它抱怨各种似乎与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 上做错了什么提供一些建议吗?

感谢期待。

4

3 回答 3

5

我对此进行了更多尝试,并在网上找到了很多示例,表明我所做的是正确的。现在这是一个工作版本...

<?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的open和close之间的换行符还在就好了

于 2013-05-16T07:47:13.497 回答
1

这适用于和不使用名称空间:

<?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"默认的。您无需指定它。

于 2016-11-12T19:08:45.400 回答
0

对于那些在 Java 中使用 Xerces 的人:它只支持xpointer="element(...)"指针。这在https://www.w3.org/TR/2003/REC-xptr-element-20030325/中定义

它有一个例子:

例如,以下指针部分标识 ID(如 XPointer 框架中定义)为“intro”的元素

但我无法理解 XPointer Framework 确定的 ID 来自https://www.w3.org/TR/2003/REC-xptr-framework-20030325/#shorthand

浏览https://www.ibiblio.org/xml/books/bible3/chapters/ch18.html
并阅读https://xerces.apache.org/xerces2-j/faq-xinclude.html
我意识到这是可能的实现您的要求:

<?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="element(/1)" />  
    <xi:include href="Test2.xml" xpointer="element(/1)" />

</ns:Root>

这样做的好处是我猜 element() 模式在比完整的 xpointer() 模式更多的地方得到支持。

注意:此寻址方案可以嵌套,例如/1/2表示根的 ( /) 1st 元素/在位置 有一个子 ( ) 2。所以它会001.2Test1.xml.

于 2021-09-16T21:06:39.603 回答