2011-05-04 50 views
1

說我有以下XML:基於屬性,合併對節點的新模板匹配

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 

    <relatedStuff> 
     <group gID="s1"> 
     <references tokID="t1"/> 
     <references tokID="t2"/> 
     </group> 

     <group gID="s2"> 
     <references tokID="t3"/> 
     </group> 

    </relatedStuff> 
</root> 

現在,考慮到for-each循環的每一個令牌將是非常低效和a bad idea,怎麼會一個去使用模板匹配,將這個XML轉換爲以下?

<s id="everything_merged"> 
    <tok id="t1" gID="s1" >blah</tok> 
    <tok id="t2" gID="s1" >blabla</tok> 

    <tok id="t3" gID="s2" >shovel</tok> 
</s> 

所有我從<s>要的是「GID」,對應於<tokens>令牌的GID。

<xsl:for-each select="b:root/a:tokens/a:token"> 
    <!-- and here some template matching --> 
    <xsl:attribute name="gID"> 
     <xsl:value-of select="--correspondingNode'[email protected]"/> 
    </xsl:attribute> 

</xsl:for-each> 

我對這種事很模糊,所以非常感謝您的幫助!

+0

問得好,+1。查看我的解決方案,獲取完整且簡短的純「推式」解決方案,該解決方案也使用密鑰。 – 2011-05-05 04:13:32

回答

2

以下樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <s id="everything_merged"> 
      <xsl:apply-templates select="/root/tokens/token" /> 
     </s> 
    </xsl:template> 
    <xsl:template match="token"> 
     <tok id="{@ID}" gID="{/root/relatedStuff/group[ 
           references[@tokID=current()/@ID]]/@gID}"> 
      <xsl:apply-templates /> 
     </tok> 
    </xsl:template> 
</xsl:stylesheet> 

應用於此輸入(良好性校正):

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 
    <relatedStuff> 
     <group gID="s1"> 
      <references tokID="t1" /> 
      <references tokID="t2" /> 
     </group> 
     <group gID="s2"> 
      <references tokID="t3" /> 
     </group> 
    </relatedStuff> 
</root> 

產地:使用密鑰和純

<s id="everything_merged"> 
    <tok id="t1" gID="s1">blah</tok> 
    <tok id="t2" gID="s1">blabla</tok> 
    <tok id="t3" gID="s2">shovel</tok> 
</s> 
+0

輝煌。我不知道你可以這樣做[]嵌套組[參考[@ tokID = current()/ @ ID]]!謝謝一堆! – Spectraljump 2011-05-05 12:09:00

1

的溶液「推式

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kgIDfromTokId" match="@gID" 
    use="../*/@tokID"/> 

<xsl:template match="tokens"> 
    <s id="everything_merged"> 
    <xsl:apply-templates/> 
    </s> 
</xsl:template> 

<xsl:template match="token"> 
    <tok id="{@ID}" gID="{key('kgIDfromTokId', @ID)}"> 
    <xsl:apply-templates/> 
    </tok> 
</xsl:template> 
</xsl:stylesheet> 

時所提供的XML文檔應用:

<root> 
    <tokens> 
     <token ID="t1">blah</token> 
     <token ID="t2">blabla</token> 
     <token ID="t3">shovel</token> 
    </tokens> 
    <relatedStuff> 
     <group gID="s1"> 
      <references tokID="t1" /> 
      <references tokID="t2" /> 
     </group> 
     <group gID="s2"> 
      <references tokID="t3" /> 
     </group> 
    </relatedStuff> 
</root> 

想要的,正確的結果產生

<s id="everything_merged"> 
    <tok id="t1" gID="s1">blah</tok> 
    <tok id="t2" gID="s1">blabla</tok> 
    <tok id="t3" gID="s2">shovel</tok> 
</s> 
+0

非常有用的答案,謝謝。你懂得越多!這會很有用,而且看起來更加優雅。你的方法和Lwburk之間有什麼性能差異? (我應該閱讀關鍵字和「推式」) – Spectraljump 2011-05-05 12:18:44

+0

@Twodordan:一旦執行了第一個key()函數,索引就建立了,函數的下一次執行幾乎都是免費的。因此,當key()函數需要被調用至少兩次時,使用鍵通常會更加高效。在這種情況下,它只被調用一次,我只是爲了方便而使用它。這個解決方案仍然可以更高效 - 取決於特定的XSLT處理器,並且需要執行測量以找出確切的性能差異以及它是否顯着。 – 2011-05-05 12:23:54