XSLT 2.0根据属性名称删除元素,并添加一组元素

时间:2015-05-26 20:51:04

标签: xml xslt

考虑下面的XML

<?xml version="1.0" encoding="UTF-8"?>
<p >
  <node>
    <e a="1"/>
    <e a="2"/>
  </node>
  <a>
    <c value="-3" v="RRR_1"/>
    <c value="1" v="RRR_2"/>
    <c value="11" v="v1"/>
    <c value="12" v="v2"/>
  </a>
</p>

我想找到所有c个元素,其v属性值以RRR开头并删除它们 然后我想在最后添加以下c节点

  <c value="123" v="RRR_134"/>
  <c value="456" v="RRR_233"/>
  <c value="789" v="RRR_900"/>

所以最终的XML看起来像

<?xml version="1.0" encoding="UTF-8"?>
<p >
  <node>
    <e a="1"/>
    <e a="2"/>
  </node>
  <a>
    <c value="11" v="v1"/>
    <c value="12" v="v2"/>
    <c value="123" v="RRR_134"/>
    <c value="456" v="RRR_233"/>
    <c value="789" v="RRR_900"/>
  </a>
</p>

我编写了以下XSL来删除带有以RRR开头的v属性的c节点 - 但是如何更改相同的XSL以在最后添加所需的元素。我可以编写另一个XSL表来执行此操作,但想知道是否可以在同一个XSLT文件中执行此操作。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/p/a/c[starts-with(@v, 'RRR')]"></xsl:template>

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

  <!-- remove new lines for a deleted element -->
  <xsl:template match="*/text()[normalize-space()]">
    <xsl:value-of select="normalize-space()"/>
  </xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

一种可能的解决方案是在最后一个c元素之后添加节点,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml"  encoding="UTF-8" indent="yes" />
   <xsl:strip-space elements="*"/>
  <xsl:template match="/p/a/c[starts-with(@v, 'RRR')]"/>
  <!-- identity transform --> 
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="c[position()=last()]">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
    <c value="123" v="RRR_134"/>
    <c value="456" v="RRR_233"/>
    <c value="789" v="RRR_900"/>
  </xsl:template>
</xsl:stylesheet>

当应用于输入XML时,会产生输出:

<?xml version="1.0" encoding="UTF-8"?>
<p>
  <node>
    <e a="1"/>
    <e a="2"/>
  </node>
  <a>
    <c value="11" v="v1"/>
    <c value="12" v="v2"/>
    <c value="123" v="RRR_134"/>
    <c value="456" v="RRR_233"/>
    <c value="789" v="RRR_900"/>
  </a>
</p>

我还删除了模板,删除了已删除元素的换行符,并添加了<xsl:strip-space elements="*"/>而添加了xsl:output属性indent="yes"以生成缩进输出。
与最后一个c元素匹配的模板会复制此元素,之后只会写入其他c个节点。