如何基于两个节点中的元素值合并xml父节点?

时间:2009-09-18 15:19:14

标签: xml xslt

我是XSLT的新手。我想基于相同的元素值组合两个节点。

这是输入文件。

<data>
  <node>
    <itemA element1="a" element2="x">
    <itemBs><other elements with element2=x></itemBs>
  </node>
    <itemA element1="a" element2="y">
    <itemBs><other elements with element2=y></itemBs>
  <node>
    <itemA element1="b" element2="z">
    <itemBs><other elements with element2=z></itemBs>
  </node>
  <node>
    <itemA element1="b" element2="w">
    <itemBs><other elements with element2=w></itemBs>
  </node>
</data>

我想组合节点与element1具有相同的值。另外,我只想保留节点itemBs的最大值为element2。

说x&gt; y,z&gt; w

这是我想要的输出

<data>
  <node>
    <itemAs>
      <itemA element1="a" element2="x">
      <itemA element1="a" element2="y">
    </itemAs>
    <itemBs>
      <itemBs><other elements with element2=x></itemBs>
    </itemBs>
  </node>
  <node>
    <itemAs>
      <itemA element1="a" element2="z">
      <itemA element1="a" element2="w">
    </itemAs>
    <itemBs>
      <itemBs><other elements with element2=z></itemBs>
    </itemBs>
  </node>
</data>

1 个答案:

答案 0 :(得分:0)

所以,似乎我理解了你的意图。

使用此输入:

<data>
  <node>
    <itemA element1="a" element2="x" />
    <itemBs><!-- other elements with element2=x --></itemBs>
  </node>
  <node>
    <itemA element1="a" element2="y" />
    <itemBs><!-- other elements with element2=y --></itemBs>
  </node>
  <node>
    <itemA element1="b" element2="z" />
    <itemBs><!-- other elements with element2=z --></itemBs>
  </node>
  <node>
    <itemA element1="b" element2="w" />
    <itemBs><!-- other elements with element2=w --></itemBs>
  </node>
</data>

这个(评论很多)XSLT 1.0方法:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />

  <!-- prepare a key to index "itemA" elements by "@element1" -->
  <xsl:key name="kItemA"  match="itemA" use="@element1" />

  <!-- the "data" element is going to be copied only -->
  <xsl:template match="data">
    <xsl:copy>
      <xsl:apply-templates />
    </xsl:copy>
  </xsl:template>

  <!-- "node" elements need special treatment -->
  <xsl:template match="node">
    <!-- retrieve a node-set of all "itemA" with the same value -->
    <xsl:variable name="itemAList" select="key('kItemA', itemA/@element1)" />

    <!-- do the following only once (for the first node in the set) -->
    <xsl:if test="generate-id(itemA[1]) = generate-id($itemAList[1])">
      <!-- copy the "node" element to the output -->
      <xsl:copy>
        <!-- copy all "itemA" elements -->
        <xsl:copy-of select="$itemAList" />

        <!-- for-each is just a vehicle to apply the desired order -->
        <xsl:for-each select="$itemAList">
          <xsl:sort select="@element2" data-type="text" order="descending" />
          <!-- when sorted descending by @element2, use first node only -->
          <xsl:if test="position() = 1">
            <!-- copy the associated "itemBs" -->
            <xsl:copy-of select="../itemBs" />
          </xsl:if>
        </xsl:for-each>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

  <!-- stray text nodes are to be ignored -->      
  <xsl:template match="text()" />

</xsl:stylesheet>

我明白了:

<data>
  <node>
    <itemA element1="a" element2="x" />
    <itemA element1="a" element2="y" />
    <itemBs>
      <!-- other elements with element2=y -->
    </itemBs>
  </node>
  <node>
    <itemA element1="b" element2="z" />
    <itemA element1="b" element2="w" />
    <itemBs>
      <!-- other elements with element2=z -->
    </itemBs>
  </node>
</data>

对于XSLT新手来说,上面的内容有点难以理解。问你是否有问题。