2009-11-28 14 views
2

我有下面的XML稍有不同:XSLT:选择不同的,但其它实例

<a> 
    <b> 
     <d>D1 content (can include child nodes)</d> 
    </b> 
    <b> 
     <c>C1 content (can include child nodes)</c> 
    </b> 
    <b> 
     <e>E1 content (can include child nodes)</e> 
    </b> 
    <b> 
     <c>C2 content (can include child nodes)</c> 
    </b> 
</a> 

使用XSLT 1.0,我需要从这个简单地生产出:“CDE”;即由节点名称排序的/ a/b /的直接子节点的名称的明确列表。每个b只有一个任意名字的孩子。

我能产生“操守准则”:

<xsl:for-each select="https://stackoverflow.com/a/b/*"> 
    <xsl:sort select="name(.)"/> 
    <xsl:value-of select="name(.)" /> 
</xsl:for-each> 

我已经使用通常的前同辈::比较尝试过,但因为每个B只有一个孩子,前面的兄弟总是一无所获。

回答

1

首先这个关键元素添加到您的XSL的顶部: -

<xsl:key name="tagNames" match="https://stackoverflow.com/a/b/*" use="name()" /> 

现在你的每个回路可以是这样的: -

<xsl:template match="/*"> 
    <xsl:for-each select="https://stackoverflow.com/a/b/*[count(. | key('tagNames', name())[1]) = 1]"> 
     <xsl:sort select="name()" /> 
     <xsl:value-of select="name()" /> 
    </xsl:for-each> 
</xsl:template> 
+0

谢谢 - 效果很好。 – sellotape 2009-11-28 19:50:51

0

您可以使用Muenchian方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="groupIndex" match="*" use="name()" /> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="a/b"/> 
    </xsl:template> 
    <xsl:template match="b"> 
     <xsl:apply-templates select="*[1][generate-id(.) = generate-id(key('groupIndex', name())[1])]" mode="group" /> 
    </xsl:template> 
    <xsl:template match="*" mode="group"> 
     <xsl:value-of select="name()"/> 
    </xsl:template> 
</xsl:stylesheet> 
+0

谢谢。我的例子显然被简化了 - 当我的XML只是一个大文档的一小部分时,它的工作是否也会如此(与那里的*匹配)? – sellotape 2009-11-28 19:56:18

+0

这可能适用于发布的简化案例,但是由于关键元素匹配文档中的__all__元素而不仅仅是/ a/b的子元素,因此会出现这种情况。 – AnthonyWJones 2009-11-28 22:26:58

+0

同意。目的是展示这个概念(并使其在示例上工作)。应该修改代码以适合现实生活场景(即使用/ a/b *作为关键字)。只是尽可能地使用模板与for-each构造。 – Goran 2009-11-29 11:47:46