基于子节点删除节点

时间:2018-05-17 05:54:29

标签: xslt xslt-1.0 xslt-2.0

目前我的XSL正在努力删除具有某些属性的节点(感谢stackoverflow)。鉴于以下xml

<Document>
  <Node1>
   <Node2>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="skip"> stuff </Node3>
  </Node2>
  <Node2>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="skip"> stuff </Node3>
  </Node2>
  <Node2>
    <Node3 etv:severity="skip"> stuff </Node3>
    <Node3 etv:severity="skip"> stuff </Node3>
    <Node3 etv:severity="skip"> stuff </Node3>
  </Node2>
 </Node1>
</Document>

使用此xsl

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

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

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

    <xsl:template match="/iso:Document/iso:Node1/iso:Node2/iso:Node3[(@etv:severity='skip')]" />
</xsl:stylesheet>

注意到Node2的第3个实例导致所有Node3出错。我想在这种情况下也删除所有节点2。这可以在1次转型中完成吗?

下面的问题,目前的输出如下

<Document>
  <Node1>
   <Node2>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="ok"> stuff </Node3>
  </Node2>
  <Node2>
    <Node3 etv:severity="ok"> stuff </Node3>
    <Node3 etv:severity="ok"> stuff </Node3>
  </Node2>
  <Node2>
  </Node2>
 </Node1>
</Document>

2 个答案:

答案 0 :(得分:1)

假设声明了正确名称空间的输入XML,您可以添加此模板:

<xsl:template match="iso:Node2[not(*/@etv:severity!='skip')]"/>

请参阅http://xsltfiddle.liberty-development.net/3NzcBsX

答案 1 :(得分:1)

让我们假设你有这个简化的输入文件(你有太多的命名空间,你真的需要它们吗?如果有必要,我会让你相应地修改样式表)

<强> INPUT:

$ more document.xml 
<Document>
  <Node1>
   <Node2>
    <Node3 severity="ok"> stuff </Node3>
    <Node3 severity="ok"> stuff </Node3>
    <Node3 severity="skip"> stuff </Node3>
  </Node2>
  <Node2>
    <Node3 severity="ok"> stuff </Node3>
    <Node3 severity="ok"> stuff </Node3>
    <Node3 severity="skip"> stuff </Node3>
  </Node2>
  <Node2>
    <Node3 severity="skip"> stuff </Node3>
    <Node3 severity="skip"> stuff </Node3>
    <Node3 severity="skip"> stuff </Node3>
  </Node2>
 </Node1>
</Document>

<强>样式表:

$ more document.xslt 
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:etv="urn:com.etv/etv" xmlns:iso="urn:iso" exclude-result-prefixes="etv iso">

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

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

    <xsl:template match="//Node2">
        <xsl:choose>
                <xsl:when test="count(./Node3[@severity='ok']) = 0">
                         <Node2></Node2><!-- you can remove this line if you do not want to have Node2 produced-->
                </xsl:when>
                <xsl:otherwise>
                        <Node2><xsl:apply-templates select="@*|node()" /></Node2>
                </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="//Node3[@severity='skip']"/>
</xsl:stylesheet>

<强>结果:

$ java -jar saxon9he.jar -s:document.xml -xsl:document.xslt
<?xml version="1.0" encoding="UTF-8"?>
<Document>
   <Node1>
      <Node2>
         <Node3 severity="ok"> stuff </Node3>
         <Node3 severity="ok"> stuff </Node3>
      </Node2>
      <Node2>
         <Node3 severity="ok"> stuff </Node3>
         <Node3 severity="ok"> stuff </Node3>
      </Node2>
      <Node2/>
   </Node1>
</Document>

您可以通过评论样式表中Node2中的行来完全删除空when。祝你好运