2013-02-07 101 views
2

從前面的問題'xslt: select unique node via intermediate reference node?'之後。XSLT:跨多個文檔創建「密鑰」?

有無論如何使用引用多個XML文檔的'鑰匙'。

喜歡的東西:

<xsl:key name="ChildByFIdAndMFId" 
    match="collection('file:///c:/temp/xslt?select=test*.xml')Child" 
    use="concat(FathersID, '+', MothersFatherID)"/> 

這給出了一個錯誤「收集功能不包括在圖案的頭部允許的」。 我想通過多個文檔引用所有匹配的「孩子」節點由FathersID和MothersFatherID來獲得一些統計結果,如sum和count。能夠在關鍵語句中使用集合看起來是一個很好的競爭者,但是我的語法錯誤或者根本不可能?

爲了詳細說明(基於上面的XML文件和代碼)...

XML文件看起來像:

<t> 
    <Children> 
     <Child> 
      <ID>1</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>200</MothersFatherID> 
      <Total>2</Total> 
     </Child> 
     <Child> 
      <ID>2</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>3</Total> 
     </Child> 
     <Child> 
      <ID>3</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>202</MothersFatherID> 
      <Total>5</Total> 
     </Child> 
     <Child> 
      <ID>4</ID> 
      <FathersID>100</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>3</Total> 
     </Child> 
     <Child> 
      <ID>5</ID> 
      <FathersID>101</FathersID> 
      <MothersFatherID>201</MothersFatherID> 
      <Total>4</Total> 
     </Child> 
    </Children> 
    <Fathers> 
     <Father> 
      <ID>100</ID> 
     </Father> 
     <Father> 
      <ID>101</ID> 
     </Father> 
    </Fathers> 
    <MothersFathers> 
     <MothersFather> 
      <ID>200</ID> 
     </MothersFather> 
     <MothersFather> 
      <ID>201</ID> 
     </MothersFather> 
     <MothersFather> 
      <ID>202</ID> 
     </MothersFather> 
    </MothersFathers> 
</t> 

最多可能會有這些文件引用的30,但我只有興趣在現在匹配子節點(其中每個文件的節點數可能爲3000個節點) - 雖然統計信息(總數)可能不同,但文件之間可能存在重複的子節點。

至今XSLT:

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


    <xsl:key name="kMFByFId" match="MothersFatherID" use="../FathersID"/> 
    <!--use="../FathersID"/>--> 

    <xsl:key name="kMFById" match="MothersFather" use="ID"/> 

    <xsl:key name="ChildByFIdAndMFId" match="Child" 
     use="concat(FathersID, '+', MothersFatherID)"/> 

    <xsl:template match="Children|MothersFathers|text()"/> 

    <xsl:template match="Father"> 

     Father ID=<xsl:value-of select="ID"/> 
     <xsl:variable name="Fid" select="ID"></xsl:variable> 

     <xsl:apply-templates select= 
      "key('kMFById', 
      key('kMFByFId', ID) 
      [generate-id(..) 
      = 
      generate-id(key('ChildByFIdAndMFId', 
      concat(../FathersID,'+',.) 
      )[1] 
      ) 
      ] 
      )"> 
      <xsl:sort select="ID" data-type="text"/> 
      <xsl:with-param name="Fid" select="$Fid"></xsl:with-param> 
     </xsl:apply-templates> 

    </xsl:template> 

    <xsl:template match="MothersFather"> 
     <xsl:param name="Fid"></xsl:param> 
     <xsl:variable name="FidAndMid" select="concat($Fid,'+',ID)"></xsl:variable> 
      MothersFather ID=<xsl:value-of select="ID"/> 
      Sum of Total= <xsl:value-of 
      select="sum(key('ChildByFIdAndMFId', $FidAndMid)/Total)"/> 
    </xsl:template> 
</xsl:stylesheet>  

所以這個工程的一個XML文檔 - 上面給出的xml:

Father ID=100 
     MothersFather ID=200 
     Sum of Total= 2 
     MothersFather ID=201 
     Sum of Total= 6 
     MothersFather ID=202 
     Sum of Total= 5 

    Father ID=101 
     MothersFather ID=201 
     Sum of Total= 4 

但是,如果我不能在關鍵使用集合,我如何去引用所有其他與當前FatherID和MothersFatherID的子節點匹配的文檔?

如果,例如,XML被複制的是兩個需要從他們拉的數據文件的輸出將有總像新和:

Father ID=100 
     MothersFather ID=200 
     Sum of Total= 6 
     MothersFather ID=201 
     Sum of Total= 18 
     MothersFather ID=202 
     Sum of Total= 15 

    Father ID=101 
     MothersFather ID=201 
     Sum of Total= 12 

我可以看到,我想使用'集合',以便我可以輕鬆地拉入所有文件,但我看不到在哪裏或如何。任何人都可以幫助我嗎?

+0

關於語法,我會在收集函數和Child元素之間加一個斜槓:'match =「collection('file:/// c:/temp/xslt?select = test * .xml')/ Child」 '。但我相信,即使這個問題得到解決,情況也會起作用。 – LarsH

+0

嗨拉爾斯,我曾試過,但仍給出了相同的錯誤集合(「文件:/// c:/ temp/xslt?選擇=測試* .xml」)功能不允許在模式的頭部' 。乾杯... – user1840734

+1

一鍵只索引一次一個文件。如果你想跨多個文件進行分組,請使用:'' –

回答

2

正如Dimitre所說,key()只搜索一個文件。如果要搜索一組文檔,很容易:使用$s/key(...)其中$ s保存文檔集。可以通過調用collection()函數,從調用document()提供一組URI,或者將多個調用的結果合併到doc()來獲得一組文檔,例如for $x in $uri-list return doc($x)

+0

嗨邁克爾,我嘗試使用'$ s/key(...)'語法顯示一個集合。但是,當我試圖用''。你能看到我在這個計劃中缺少的東西嗎?我是否必須事先將我的鑰匙初始化到收藏清單中?謝謝,布萊斯。 – user1840734

+0

@ user1840734,key()的第一個參數是'ChildByFIdAndMFId'。這個參數應該是關鍵字的一個字符串。由於您沒有引號,因此它被解釋爲子元素的名稱 - 可能不存在,因此會出現「空序列」錯誤。試試'$ s/key('ChildByFIdAndMFId',$ FidAndMid)' – LarsH

+0

D'oh!所以有些日子很愚蠢...無論如何,愛你的答案 - 很簡單,看看代碼中現在發生了什麼事情,使用單行程序和沒有for-each-group循環。乾杯,布萊斯。 – user1840734