使用XSLT删除XML中未定义级别的重复条目

时间:2012-04-16 15:29:49

标签: xml xslt

我对XSL转换很陌生这里是个问题。如果我有这个xml文件:

    <root> 
        <node id="a">
            <section id="a_1">
               <item id="0">
                    <attributes>
                        <color>Red</color>
                    </attributes>
               </item>
            </section>
            <section id="a_2">
               <item id="0">
                    <attributes>
                        <color>Red</color>
                    </attributes>
               </item>
            </section>            
        </node>

        <node id="b">
            <section id="b_1">
                <user id="b_1a">
                    <attribute>
                        <name>John</name>
                    </attribute>
                </user>

                <user id="b_1b">
                    <attribute></attribute>
                </user>

                <user id="b_1a">
                    <attribute>
                        <name>John</name>    
                    </attribute>
                </user>
            </section>
        </node>
 </root>

我希望输出如下:

<root> 
        <node id="a">
            <section id="a_1">
               <item id="0">
                    <attributes>
                        <color>Red</color>
                    </attributes>
               </item>
            </section>
            <section id="a_2">
               <item id="0">
                    <attributes>
                        <color>Red</color>
                    </attributes>
               </item>
            </section>            
        </node>

        <node id="b">
            <section id="b_1">
                <user id="b_1a">
                    <attribute>
                        <name>John</name>
                    </attribute>
                </user>

                <user id="b_1b">
                    <attribute></attribute>
                </user>

            </section>
        </node>
 </root>

问题是我不知道关卡的深度有多深,但只要它处于同一级别且有重复,我们就将其删除。 这可能吗?我一直在努力解决这个问题并且没有任何线索。 任何帮助将不胜感激。

欢呼声, 约翰

1 个答案:

答案 0 :(得分:2)

试试这个:

<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>

  <!--If you want to remove any duplicate element (not just user,
  change the match to: match="*[@id = preceding::*/@id]"-->
  <xsl:template match="user[@id = preceding::user/@id]"/>

</xsl:stylesheet>

另外,我不确定“在同一级别”是什么意思,但如果元素名称也必须匹配,请使用此模板:(注意:此模板在Saxon 9.3中有效,但在Xalan中没有或撒克逊人6.5.5。)

<xsl:template match="*[@id = preceding::*[name() = name(current())]/@id]"/>

更新:这是一个似乎适用于Xalan和Saxon 6.5.5的模板:

  <xsl:template match="*[@id = preceding::*/@id]">
    <xsl:if test="not(@id = preceding::*[name() = name(current())]/@id)">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>