如何根据不同元素的值过滤xml元素?

时间:2014-07-21 10:07:58

标签: xml xslt

我有这个xml('其他'元素有不同的名称,为了清楚起见,只是跳过它们):

<root>
<elements1>
<element>
<id>1</id>
<other>a</other>
<other>b</other>
<other>c</other>
</element>
<element><id>2</id>
<other>a</other>
<other>b</other>
<other>c</other>
</element>
<element><id>3</id>
<other>a</other>
<other>b</other>
<other>c</other>
</element>
</elements1>

<elements2>
<element>
<id2>1</id2>
<other2>a</other2>
<other2>b</other2>
<other2>c</other2>
</element>
<element>
<id2>2</id2>
<other2>a</other2>
<other2>b</other2>
<other2>c</other2>
</element>
<elements2>
</root>

我需要对其进行过滤,以便显示如下内容:

<root>
 <elements>
  <element>
   <id>1</id>
   <id2>1</id2>
   <other>a</other>
   <other>b</other>
   <other>c</other>
   <other2>a</other2>
   <other2>b</other2>
   <other2>c</other2>
  </element>
  <element>
   <id>2</id>
   <id2>2</id2>
   <other>a</other>
   <other>b</other>
   <other>c</other>
   <other2>a</other2>
   <other2>b</other2>
   <other2>c</other2>
  </element>
</elements>
</root>

所以它应该把两个不同元素的子节点放在一起作为一个元素过滤id和id2。

不确定怎么做。我已经尝试了两个for-each元素来过滤xml,但它不起作用。

1 个答案:

答案 0 :(得分:1)

这是一个使用密钥的XSLT 2.0样式表:

<xsl:stylesheet 
  version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:key name="id2" match="elements2/element" use="id2"/>

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

<xsl:template match="root">
  <xsl:copy>
    <elements>
      <xsl:apply-templates select="elements1/element[key('id2', id)]"/>
    </elements>
  </xsl:copy>
</xsl:template>

<xsl:template match="elements1/element">
  <xsl:variable name="el2" select="key('id2', id)"/>
  <xsl:copy>
    <xsl:copy-of select="id, $el2/id2, (., $el2)/(* except (id, id2))"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>

与XSLT 1.0类似的方法是

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:key name="id2" match="elements2/element" use="id2"/>

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

<xsl:template match="root">
  <xsl:copy>
    <elements>
      <xsl:apply-templates select="elements1/element[key('id2', id)]"/>
    </elements>
  </xsl:copy>
</xsl:template>

<xsl:template match="elements1/element">
  <xsl:variable name="el2" select="key('id2', id)"/>
  <xsl:copy>
    <xsl:copy-of select="id | $el2/id2 | *[not(self::id)] | $el2/*[not(self::id2)]"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>