2010-07-15 63 views
1

如果我運行下面的XSLT代碼:計數在XSLT不同的項目深度無關

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

<xsl:key name="kValueByVal" match="variable_name/@value" 
    use="."/> 

<xsl:template match="assessment"> 
    <xsl:for-each select=" 
    /*/*/variable/attributes/variable_name/@value 
      [generate-id() 
      = 
       generate-id(key('kValueByVal', .)[1]) 
      ] 
    "> 
    <xsl:value-of select= 
    "concat(., ' ', count(key('kValueByVal', .)), '&#xA;')"/> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

以下XML:

<assessment> 
    <variables> 
     <variable> 
      <attributes> 
       <variable_name value="FRED"/> 
      </attributes> 
     </variable> 
    </variables> 
    <variables> 
     <variable> 
      <attributes> 
       <variable_name value="MORTIMER"/> 
      </attributes> 
     </variable> 
    </variables> 
    <variables> 
     <variable> 
      <attributes> 
       <variable_name value="FRED"/> 
      </attributes> 
     </variable> 
    </variables> 
</assessment> 

我得到所需的輸出:

FRED 2 
MORTIMER 1 

(如需要,請參閱my original question以瞭解更多信息。)

不過,如果我對這個投入運行:

<ExamStore> 
    <assessment> 
     <variables> 
      <variable> 
       <attributes> 
        <variable_name value="FRED"/> 
       </attributes> 
      </variable> 
     </variables> 
     <variables> 
      <variable> 
       <attributes> 
        <variable_name value="MORTIMER"/> 
       </attributes> 
      </variable> 
     </variables> 
     <variables> 
      <variable> 
       <attributes> 
        <variable_name value="FRED"/> 
       </attributes> 
      </variable> 
     </variables> 
    </assessment> 
</ExamStore> 

我什麼也沒得到。 (請注意,我只是將原始輸入包裹在ExamStore標記中。)我期待並希望得到相同的輸出。

爲什麼我不?如何更改原始XSLT代碼以獲得相同的輸出?

+0

+1試圖找到真相。查看我的答案,解釋問題並提供解決方案。 – 2010-07-16 03:02:51

回答

1

那麼您的選擇xpath /*/*/variable/attributes/variable_name/...不再正確,因爲您在節點樹中添加了更高的另一個節點。

如果你想擁有真正的獨立,你需要使用類似:

//variable/attributes/variable_name/... 

...(而不是在開始雙斜槓),但是這是相當危險的,因爲它會趕上的是所有出現結構 - 確定這就是你的意思。

否則,只需與另一/*

0

預先考慮您的XPath真正的結構獨立你應該使用:

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

<xsl:key name="kValueByVal" match="variable_name/@value" 
    use="."/> 

<xsl:template match="variable_name[@value 
      [generate-id() 
      = 
       generate-id(key('kValueByVal', .)[1]) 
      ]]"> 
    <xsl:value-of select= 
    "concat(@value, ' ', count(key('kValueByVal', @value)), '&#xA;')"/> 
</xsl:template> 
</xsl:stylesheet> 

結果與第一次輸入:

FRED 2 
MORTIMER 1 

結果與第二輸入:

FRED 2 
MORTIMER 1 

注意:切勿將//用作fisrt XPath運算符。

1

當您在XML文檔中引入了另一個級別時,這將原始解決方案中使用的絕對XPath表達式(在原始XML文件後緊跟其後)徹底搞砸了。

因此,爲了使在新形勢下的XPath表達式的工作,只是做到以下幾點:

更換

/*/*/variable/attributes/variable_name/@value 

/*/*/*/variable/attributes/variable_name/@value 

和現在你又得到了通緝令:

FRED 2 
MORTIMER 1 

我永遠不會給你一個「獨立的」解決方案,因爲你還沒有提供任何關於你想應用轉換的可能XML文檔集的任何屬性/保證/約束。

在你原來的問題,你使用:

.//variables/variable/attributes/variable_name 

關閉assessment

,這就是爲什麼我在我的解決方案中使用的絕對XPath表達式。不能保證在另一個XML文檔中某些variable_name元素不存在,因此它們的祖先鏈不是variables/variable/attributes,如果是這種情況,這將意味着您可能對這種「不規則」的值不感興趣variable_name元素。

本課是一個不應該太具體定義一個問題,然後想要一般的解決方案。 :)