如何使用xslt删除xml中的某些节点?

时间:2011-03-21 10:17:59

标签: xml xslt

有没有人知道如何使用xslt进行以下转换?

源代码:

<?xml version="1.0" encoding="UTF-8"?>
<body>
  <termEntry id="1">
   <langSet lang="eng-us">
    <ntig>
     <termGrp>
      <term></term>
     </termGrp>
    </ntig>
    <ntig>
     <termGrp>
      <term></term>
     </termGrp>
    </ntig>
   </langSet>

   <langSet lang="ara-ae">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
</termEntry>

<termEntry id="2">
 <langSet lang="eng-us">
  <ntig>
   <termGrp>
    <term></term>
   </termGrp>
  </ntig>
  <ntig>
   <termGrp>
    <term></term>
   </termGrp>
  </ntig>
  <ntig>
   <termGrp>
    <term>123</term>
   </termGrp>
  </ntig>
 </langSet>
</termEntry>
</body>

请求: 1.如果<term></term>中的值为null \ empty,则删除其祖父节点,即

<ntig></ntig>

2.这样,如果所有<term>标记都为空,请删除整个<langset>节点。

预期结果

<?xml version="1.0" encoding="UTF-8"?>
<body>
  <termEntry id="1">

   <langSet lang="ara-ae">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
  </termEntry>

  <termEntry id="2">
   <langSet lang="eng-us">
    <ntig>
     <termGrp>
      <term>123</term>
     </termGrp>
    </ntig>
   </langSet>
 </termEntry>
</body>

2 个答案:

答案 0 :(得分:3)

您需要身份转换以及几个简单的空模板。您希望将所有输​​入复制到输出中,除非它符合您的条件,在这种情况下您要禁止它。

样式表,例如:

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

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

    <xsl:template match="ntig[descendant::term[. = '']]"/>
    <xsl:template match="langSet[not(descendant::term[. != ''])]"/>

</xsl:stylesheet>

将做你需要的。匹配ntig元素的模板将禁止那些具有空term个孙子元素的元素。匹配langSet元素的模板会抑制那些没有带有内容的后代langSets元素的term

答案 1 :(得分:1)

此转化

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

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

 <xsl:template match="ntig[not(*/term[string-length()>0])]"/>
 <xsl:template match="langSet[not(*/*/term[string-length()>0])]"/>
</xsl:stylesheet>

应用于提供的XML文档

<body>
    <termEntry id="1">
        <langSet lang="eng-us">
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
        </langSet>
        <langSet lang="ara-ae">
            <ntig>
                <termGrp>
                    <term>123</term>
                </termGrp>
            </ntig>
        </langSet>
    </termEntry>
    <termEntry id="2">
        <langSet lang="eng-us">
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term></term>
                </termGrp>
            </ntig>
            <ntig>
                <termGrp>
                    <term>123</term>
                </termGrp>
            </ntig>
        </langSet>
    </termEntry>
</body>

产生想要的结果

<body>
   <termEntry id="1">
      <langSet lang="ara-ae">
         <ntig>
            <termGrp>
               <term>123</term>
            </termGrp>
         </ntig>
      </langSet>
   </termEntry>
   <termEntry id="2">
      <langSet lang="eng-us">
         <ntig>
            <termGrp>
               <term>123</term>
            </termGrp>
         </ntig>
      </langSet>
   </termEntry>
</body>

<强>解释

  1. 身份规则(模板)按“原样”复制每个节点。

  2. 覆盖ntig[not(*/term[string-length()>0])]身份规则的模板有一个空主体 - 这实际上忽略(删除)任何ntig个没有至少term个元素的元素阳性string-length()的孙子。

  3. 覆盖langSet[not(*/*/term[string-length()>0])]身份规则的模板有一个空主体 - 这实际上忽略(删除)任何langSet个没有至少term个元素的元素有正面的曾孙[{1}}。

  4. 请注意指定此类模板违反了问题的定义:

    string-length()

    因为要求是“如果值in null为空,则删除其祖父母节点”。

    但是,上面的第一个模板不仅会删除祖父<xsl:template match="ntig[descendant::term[. = '']]"/> <xsl:template match="langSet[not(descendant::term[. != ''])]"/> ,还会删除任何祖先 ntig

    当前解决方案不会犯这样的错误