2011-08-30 93 views
7

我对xslt变换颇为陌生,我需要一种转换帮助。我需要通过它的属性和列出每种属性的父项将某些类型的所有节点分组。它是一种制作文件中某些东西用法的总结。我将介绍一个简单的例子。
输入:通过XSLT中的属性值对XML节点进行分组

<root> 
<node name="node1"> 
    <somechild child-id="1"> 
</node> 
<node name="node2"> 
    <somechild child-id="2"> 
</node> 
<node name="node3"> 
    <somechild child-id="1"> 
</node> 
<node name="node4"> 
    <somechild child-id="2"> 
</node> 
<node name="node5"> 
    <somechild child-id="3"> 
</node> 
</root> 

所需的输出:

<root> 
<somechild child-id="1"> 
    <is-child-of> 
     <node name="node1" /> 
     <node name="node3" /> 
    </is-child-of> 
</somechild> 
<somechild child-id="2"> 
    <is-child-of> 
     <node name="node2" /> 
     <node name="node4" /> 
    </is-child-of> 
</somechild> 
<somechild child-id="3"> 
    <is-child-of> 
     <node name="node5" /> 
    </is-child-of> 
</somechild> 
</root> 

想法是,如果在许多节点的相同元素,他们具有相同的孩子-ID。 我需要找到所有使用的每个。 我发现这个问题XSLT transformation to xml, grouping by key这是有点类似,但有一个开始的所有作者的声明,我没有这样的,是总是只有一个孩子。

回答

5
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="k" match="somechild" use="@child-id"/> 
    <xsl:key name="n" match="node" use="somechild/@child-id"/> 

    <xsl:template match="root"> 
     <xsl:copy> 
      <xsl:apply-templates 
       select="//somechild[generate-id(.) = generate-id(key('k', @child-id))]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="somechild"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 

      <is-child-of> 
       <xsl:apply-templates select="key('n', @child-id)"/> 
      </is-child-of> 
     </xsl:copy> 

    </xsl:template> 

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

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

</xsl:stylesheet> 

输出:

<root> 
    <somechild child-id="1"> 
    <is-child-of> 
     <node name="node1" /> 
     <node name="node3" /> 
    </is-child-of> 
    </somechild> 
    <somechild child-id="2"> 
    <is-child-of> 
     <node name="node2" /> 
     <node name="node4" /> 
    </is-child-of> 
    </somechild> 
    <somechild child-id="3"> 
    <is-child-of> 
     <node name="node5" /> 
    </is-child-of> 
    </somechild> 
</root> 
+0

非常感谢您!使用这个例子,我能够对我的问题进行转换! – Pax0r

+0

@ Pax0r,不客气! –

1

您可以尝试以下方法吗?

<!-- select the current child id to filter by --> 
<xsl:variable name="id" select="somechild/@child-id"/> 
<!-- select the nodes which have a somechild element with the child-id to look for --> 
<xsl:for-each select="/root//some-child[@child-id = $id]/.."> 
    <!-- for each such node, do something --> 
</xsl:for-each>