合并2 XML包括不匹配的节点

时间:2014-02-19 21:09:23

标签: xslt

我有两个XML文件, a b 。我想在某个子级别合并,某些节点具有属性。当节点名称和属性匹配时,我希望复制子节点。如果有不匹配的节点,我也想要那些。我在这里给出了一个示例,其中复制了 a 的所有节点,但我只获得 b 的匹配节点(它们被合并)。如何获得 b 的无法匹配的节点?

文件 a.xml

<level0>
  <level1>
    <level2 value="21">
      <level3 value="31">
        <a>A31</a>
      </level3>
      <level3 value="32">
        <a>A32</a>
      </level3>
    </level2>
    <level2 value="22">
      <level3 value="33">
        <a>A33</a>
      </level3>
    </level2>
  </level1>
</level0>   

档案 b.xml

<level0>
  <level1>
    <level2 value="21">
      <level3 value="31">
        <b>B31</b>
      </level3>
    </level2>
    <level2 value="22">
      <level3 value="33">
        <b>B33</b>
      </level3>
      <level3 value="34">
        <b>B34</b>
      </level3>
    </level2>
  </level1>
</level0> 

使用XSL(下方),我可以将 b 合并到 a ,但 b 中的此节点会被删除,因为没有匹配项在 a

<level3 value="34">
  <b>B34</b>
</level3>

我的输出如下:

<?xml version="1.0" encoding="ISO-8859-1"?>
<level0>
  <level1>
    <level2 value="21">
      <level3 value="31">
        <a>A31</a>
      <b>B31</b></level3>
      <level3 value="32">
        <a>A32</a>
      </level3>
    </level2>
    <level2 value="22">
      <level3 value="33">
        <a>A33</a>
      <b>B33</b></level3>
    </level2>
  </level1>
</level0>

这是我目前的XSL。运行它: xsltproc ab.xsl b.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="ISO-8859-1" indent="yes" />
    <xsl:variable name="with" select="'b.xml'" />

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="level3">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
            <xsl:variable name="info" select="document($with)//*/level2[@value=current()/../@value]/level3[@value=current()/@value]/." />
            <xsl:for-each select="$info/*">
                <xsl:copy-of select="." />
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:transform>

我敢打赌这很容易,但XSL不是我的事,我很少需要使用它。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

据我所知,没有必要编写自己的合并样式表。使用由Oliver Becker开发的合并算法。您可以在线找到代码here

运行样式表的最简单方法是创建一个XML文件,汇总应合并的文件:

摘要输入XML

<?xml version="1.0"?>
<merge xmlns="http://informatik.hu-berlin.de/merge">
   <file1>a.xml</file1>
   <file2>b.xml</file2>
</merge> 

当应用于两个输入文件时,这是我得到的输出:

<强>输出

<?xml version="1.0" encoding="UTF-8"?><level0>
  <level1>
    <level2 value="21">
      <level3 value="31">
        <a>A31</a>
      <b>B31</b>
      </level3>
      <level3 value="32">
        <a>A32</a>
      </level3>
    </level2>
    <level2 value="22">
      <level3 value="33">
        <a>A33</a>
      <b>B33</b>
      </level3>
    <level3 value="34">
        <b>B34</b>
      </level3>
    </level2>
  </level1>
</level0>

输出在一个方面与预期输出不同:<level3 value="34">在预期输出中不存在,正如@LegoStormtroopr已经指出的那样。

请注意,XSLT(或一般XML)中的“intersection”和“union”不一定与SQL中的概念相同。