代码之家  ›  专栏  ›  技术社区  ›  Kyle

不同节点上的xslt?

  •  1
  • Kyle  · 技术社区  · 14 年前

    我有以下架构:

    <parent>
      <child id="1" name="Child 1 Version 1" />
    </parent>
    <parent>
      <child id="2" name="Child 2 Version 1" />
    </parent>
    <parent>
      <child id="1" name="Child 1 Version 2" />
    </parent>
    

    我只想处理每个id的最后一个节点。下面是我根据一些阅读尝试的内容:

      <xsl:for-each select="//parent/child">
        <xsl:sort select="@id"/>
        <xsl:if test="not(@id=following-sibling::*/@id)">
          <xsl:element name="child">
            <xsl:value-of select="@name"/>
          </xsl:element>
        </xsl:if>
      </xsl:for-each>
    

    但似乎没用。我的输出仍然包含所有三个元素。我能做些什么来纠正我的问题吗?

    2 回复  |  直到 12 年前
        1
  •  2
  •   Dimitre Novatchev    14 年前

    我只想处理最后一个 每个id的节点。下面是我的 在阅读的基础上尝试:

      <xsl:for-each select="//parent/child"> 
        <xsl:sort select="@id"/> 
        <xsl:if test="not(@id=following-sibling::*/@id)"> 
          <xsl:element name="child"> 
            <xsl:value-of select="@name"/> 
          </xsl:element> 
        </xsl:if> 
      </xsl:for-each> 
    

    但似乎没用。我的 元素。有什么我能做的吗

    这个代码的问题是 即使节点在排序的节点集中 following-sibling

    为了让这段代码工作,首先要创建一个全新的文档,其中的节点按所需的方式排序,然后(在XSLT 1.0中,必须使用 xxx:node-set() 对生成的RTF进行扩展,使其成为一个普通的XML文档)在该文档上,节点根据需要有自己的兄弟节点。

    解决方案 :

    此转换提供了一个可能的不需要使用扩展函数的XSLT 1.0解决方案:

    <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:key name="kchildById" match="child" use="@id"/>
    
     <xsl:template match="/*">
      <t>
        <xsl:apply-templates select=
        "*/child[generate-id()
                =
                 generate-id(key('kchildById',
                                 @id)[last()]
                             )
                ]
        "/>
      </t>
     </xsl:template>
    
     <xsl:template match="child">
      <child>
       <xsl:value-of select="@name"/>
      </child>
     </xsl:template>
    </xsl:stylesheet>
    

    当应用于提供的XML片段时 (包装在顶部元素中,成为格式良好的XML文档,并为 id="2"

    <t>
        <parent>
            <child id="1" name="Child 1 Version 1" />
        </parent>
        <parent>
            <child id="2" name="Child 2 Version 1" />
        </parent>
        <parent>
            <child id="1" name="Child 1 Version 2" />
        </parent>
        <parent>
            <child id="2" name="Child 2 Version 2" />
        </parent>
    </t>
    

    产生想要的结果 :

    <t>
       <child>Child 1 Version 2</child>
       <child>Child 2 Version 2</child>
    </t>
    

    做笔记

        2
  •  1
  •   user357812 user357812    14 年前

    此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:key name="kParentByChildId" match="parent" use="child/@id"/>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="parent[count(.|key('kParentByChildId',
                                                child/@id)[last()]) != 1]"/>
    </xsl:stylesheet>
    

    输出:

    <root>
        <parent>
            <child id="2" name="Child 2 Version 1"></child>
        </parent>
        <parent>
            <child id="1" name="Child 1 Version 2"></child>
        </parent>
    </root>
    

    注意

    编辑 :以防混淆。上述样式表是指: 抄袭一切 child 没有最后一个 @id 同类的 . 所以,它不是选择组中的最后一个,而是作为反向逻辑,分条不是组中的最后一个。

    following-sibling 轴心。您寻找第一种类型的方法是从以前很少有处理器实现密钥的时代开始的。现在那些日子已经过去了。

    所以,这个样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:template match="t">
            <xsl:for-each select="parent/child">
                <xsl:sort select="@id"/>
                <xsl:if test="not(@id=following::child/@id)">
                    <xsl:element name="child">
                        <xsl:value-of select="@name"/>
                    </xsl:element>
                </xsl:if>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    <child>Child 1 Version 2</child>
    <child>Child 2 Version 1</child>
    

    注意 : following 轴心,因为 小孩