2009-11-28 17 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