2013-06-04 58 views
0

我想列出包含某個子節點的所有節點中的某個特定ID。使用XSLT映射XML內容

拿這個示例XML:

<foo> 
    <bar name="hello"> 
    <baz id="1" /> 
    </bar> 
    <bar name="there"> 
    <baz id="1" /> 
    <baz id="2" /> 
    </bar> 
    <bar name="world"> 
    <baz id="3" /> 
    </bar> 
</foo> 

我拿出其中包含兩個嵌套循環for-each

<xsl:for-each select="/foo/bar/baz"> 
    <xsl:variable name="id" select="@id" /> 
    <xsl:value-of select="$id" /> 
    <ul> 
     <xsl:for-each select="/foo/bar/baz"> 
     <xsl:variable name="local_id" select="@id" /> 
     <xsl:variable name="bar_name" select="../@name" /> 

     <xsl:if test="$id = $local_id"> 
      <li><xsl:value-of select="$bar_name" /></li> 
     </xsl:if> 

     </xsl:for-each> 
    </ul> 
</xsl:for-each> 

其中給出以下結果如下XSLT模板

1 
- hello 
- there 
1 
- hello 
- there 
2 
- there 
3 
- world 

問題是第一個鍵/值對是重複的。

回答

1

爲了保持解決方案,因爲它是可以改變第一換每次只考慮一個id的第一次出現。

<xsl:for-each select="/foo/bar/baz[not (preceding::baz/@id = @id)] "> 

這是迄今爲止不是這種「問題」的最佳解決方案。 爲了改善這種看看爲「分組使用Muenchian法」( 並且還更好的做法是使用應用模板,而不是換每個

設在這裏的一個關鍵的解決方案:。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:key name="kBazId" match="bar/baz" use="@id"/> 

    <xsl:template match="/" > 
     <xsl:for-each select="/foo/bar/baz[count(. | key('kBazId', @id)[1])=1]" > 
      <xsl:value-of select="@id" /> 
      <ul> 
       <xsl:apply-templates select="key('kBazId', @id)/.." /> 
      </ul> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="bar"> 
     <li> 
      <xsl:value-of select="@name"/> 
     </li> 
    </xsl:template> 
</xsl:stylesheet> 
+0

太好了!很有用,謝謝! – Theodor