如何使用XSLT从XML文件中删除不需要的元素和属性

时间:2011-05-12 23:37:05

标签: xml xslt

我有XML文件,我想按原样复制它,但我想过滤一些不需要的元素和属性,例如以下是原始文件:

<root>
<e1 att="test1" att2="test2"> Value</e1>
<e2 att="test1" att2="test2"> Value 2 <inner class='i'>inner</inner></e2>
<e3 att="test1" att2="test2"> Value 3</e3>

</root>

过滤后( e3 元素和 att2 属性已删除):

<root>
<e1 att="test1" > Value</e1>
<e2 att="test1" > Value 2 <inner class='i'>inner</inner></e2>
</root>

备注:

  • 我更喜欢使用( for-each 元素而不是 apply-templates ,如果可能的话)
  • 我遇到了 xsl:element xsl:attribute 的问题,因为我无法编写当前节点名称

谢谢

2 个答案:

答案 0 :(得分:9)

我知道您更愿意使用for-each,但为什么不使用身份转换,然后使用您不想保留的内容覆盖该模板?

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="e3|@att2"/>

</xsl:stylesheet>

产生

<root>
   <e1 att="test1"> Value</e1>
   <e2 att="test1"> Value 2 <inner class="i">inner</inner>
   </e2>
</root>

答案 1 :(得分:1)

正如@DevNull向您展示的那样,使用身份变换更容易,更简洁。无论如何,这是一个可能的解决方案for-each,而不是apply-templates,如您所要求的那样:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:template match="/root">
   <root>
    <xsl:for-each select="child::node()">
     <xsl:choose>
      <xsl:when test="position()=last()-1"/>
      <xsl:otherwise>
       <xsl:copy>
        <xsl:copy-of select="@att"/>
        <xsl:copy-of select="child::node()"/>
       </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
   </xsl:for-each>
  </root>
</xsl:template>


关于使用身份转换的注意事项

如果您的情况确实如此,我的意思是未知的元素名称,@ DevNull将不起作用,您需要更一般的东西:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
   <xsl:strip-space elements="*"/>

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

    <xsl:template match="root/child::node()[position()=last()]|@att2"/>

</xsl:stylesheet>

此解决方案即使使用最后一个元素e4e1000也可以使用。