如何使用xslt过滤和删除xml文件中的某些节点

时间:2012-10-09 08:37:26

标签: xslt xslt-1.0

我有这个xml文件:

<A>
<B>
    <elt>Add</elt>
    ...there are some element here
    <bId>2</bId>
</B>
<B>
    <elt>Add</elt>
    ...there are some element here
    <bId>2</bId>
</B>
<B>
    <elt>Add</elt>
    ...there are some element here
    <bId>2</bId>
</B>
<B>
    <elt>can</elt>
    ...there are some element here
    <bId>3</bId>
</B>
<B>
    <elt>can</elt>
    ...there are some element here
    <bId>3</bId>
</B>

我想检查每个 bId 元素的值。如果此值与前面或后面的 bId 元素相同,那么我将把bloc B 的其他元素放在另一个集合中,除了元素 bId < / strong>将在转换后被拒绝。为了让您的问题得到理解,这是预期的输出:

<CA>
  <cplx>
    <spRule>
            <elt>Add</elt>
             ...
    </spRule>
    <spRule>
            <elt>Add</elt>
             ...
    </spRule>
    <spRule>
            <elt>Add</elt>
            ...
    </spRule>
  </cplx>
  <cplx>
    <spRule>
            <elt>can</elt>
            ...
    </spRule>
    <spRule>
            <elt>can</elt>
            ...
    </spRule>
  </cplx>
</CA>

即使xml文件中的元素没有按 bId 的值排序,我也希望获得相同的预期输出。 我尝试使用这个xsl代码:

<xsl:for-each select="bId"
  <CA>
    <cplx>
    <xsl:choose>
      <xsl:when test="node()[preceding::bId]">
         <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates/>
         </xsl:copy>
      </xsl:when>
    </cplx>
  </CA>
</xsl:for-each>

但它没有走路。有人可以帮帮我吗? 感谢

1 个答案:

答案 0 :(得分:2)

假设你想要的第一个描述是将具有相同bId值的相邻元素分组,那么XSLT 1.0的方法如下:

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

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:key name="k1"
    match="B[bId = preceding-sibling::B[1]/bId]"
    use="generate-id(preceding-sibling::B[not(bId = preceding-sibling::B[1]/bId)][1])"/>

  <xsl:template match="A">
    <CA>
      <xsl:apply-templates select="B[not(preceding-sibling::B[1]) or not(bId = preceding-sibling::B[1]/bId)]"/>
    </CA>
  </xsl:template>

  <xsl:template match="B">
    <cplx>
      <xsl:apply-templates select=". | key('k1', generate-id())" mode="sp"/>
    </cplx>
  </xsl:template>

  <xsl:template match="B" mode="sp">
    <spRule>
      <xsl:copy-of select="node()[not(self::bId)]"/>
    </spRule>
  </xsl:template>

</xsl:stylesheet>

如果您只想将具有相同B值的所有bId元素分组,请使用

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

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

  <xsl:key name="k1"
    match="B"
    use="bId"/>

  <xsl:template match="A">
    <CA>
      <xsl:apply-templates select="B[generate-id() = generate-id(key('k1', bId)[1])]"/>
    </CA>
  </xsl:template>

  <xsl:template match="B">
    <cplx>
      <xsl:apply-templates select="key('k1', bId)" mode="sp"/>
    </cplx>
  </xsl:template>

  <xsl:template match="B" mode="sp">
    <spRule>
      <xsl:copy-of select="node()[not(self::bId)]"/>
    </spRule>
  </xsl:template>

</xsl:stylesheet>