2011-11-30 18 views
1

用下面的文件作爲XSLTProcessor中的輸入:組兩個XML文件像SQL基由

mylibrary.xml:

<library> 
    <book isbn="1"/>  
    <book isbn="3"/> 
    <book isbn="5"/> 
</library> 

,這一個可用於: bookreference.xml:

<reference> 
    <book isbn="1"> 
     <category>SF</category> 
    </book> 
    <book isbn="2"> 
     <category>SF</category> 
    </book> 
    <book isbn="3"> 
     <category>SF</category> 
    </book> 
    <book isbn="4"> 
     <category>Comedy</category> 
    </book> 
    <book isbn="5"> 
     <category>Comedy</category> 
    </book> 
</reference> 

我想要得到我在mylibrary,groupby類,使用xslt 1-0得到的書的數量。

輸出想要的東西:

SF : 2 book(s) 
Comedy : 1 book(s) 

這裏是xsl我寫使用馬丁Honnen法解釋「用2個不同的XML文件作爲音源時分組? , 我認爲解決問題,但我還沒有驗證,也許有人有更好的解決方案。

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" 
    exclude-result-prefixes="exsl" 
    version="1.0"> 

<xsl:output method="xml" indent="yes"/> 
<xsl:key name="book-by-category" match="book" use="category"/> 

<xsl:param name="bookref" select="'bookreference.xml'"/> 
<xsl:variable name="doc" select="document($bookref)/reference"/> 

<xsl:variable name="rtf"> 
    <xsl:apply-templates select="//library" mode="merge"/> 
</xsl:variable> 

<xsl:template match="library" mode="merge"> 
    <xsl:element name="mybookcat"> 
    <xsl:for-each select="book"> 
     <xsl:variable name="isbn" select="@isbn"/> 
     <xsl:element name="book"> 
     <xsl:attribute name="isbn"><xsl:value-of select="$isbn"/></xsl:attribute> 
     <xsl:for-each select="$doc/book[@isbn=$isbn]"> 
      <xsl:element name="category"> 
       <xsl:value-of select="./category"/> 
      </xsl:element> 
     </xsl:for-each> 
     </xsl:element> 
    </xsl:for-each> 
    </xsl:element> 
</xsl:template>  

<xsl:template match="/"> 
    <xsl:apply-templates select="exsl:node-set($rtf)/mybookcat"/> 
</xsl:template> 

<xsl:template match="mybookcat"> 
<xsl:for-each select="book[count(. | key('book-by-category',category)[1]) = 1]"> 
    <xsl:sort select="category"/> 
    <xsl:value-of select="category" /><xsl:text> : </xsl:text> 
    <xsl:variable name="current-cat" select="key('book-by-category', category)"/> 
    <xsl:value-of select="count($current-cat)"/><xsl:text> book(s) 
</xsl:text> 
    <xsl:for-each select="key('book-by-category', category)"> 
     <xsl:sort select="@isbn" data-type="number" /> 
     <xsl:value-of select="@isbn" /><xsl:text> 
</xsl:text>    
    </xsl:for-each> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 
+0

@_seb:這是我連續第二次給你更好的答案 - 希望你對此有所瞭解。順便說一句,+1這使你的原始問題的選擇也很有趣。 –

+0

@_dimitre:當然,我真的很感謝你的幫助,我知道你花了很多時間在幫忙。 – Seb

回答

2

這裏是我寫的用馬丁Honnen方法 解釋XSL'使用2個不同的XML文件作爲音源時分組? ,我認爲 解決這個問題,但我還沒有驗證,也許有人有 更好的解決方案

下面是一個簡單的XSLT 1.0解決方案,不使用任何擴展功能或xsl:for-each

<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="kBookByCat" match="book" 
      use="category"/> 

    <xsl:variable name="vRef" select= 
    "document('file:///c:/temp/delete/reference.xml')"/> 

    <xsl:variable name="vMyIsbns" select="/*/*/@isbn"/> 

    <xsl:variable name="vResult"> 
     <xsl:apply-templates select="$vRef/*"/> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <xsl:copy-of select="$vResult"/> 
    </xsl:template> 

    <xsl:template match= 
     "book[generate-id() 
      = 
      generate-id(key('kBookByCat', category)[1]) 
      ] 
     "> 
     <xsl:variable name="vBooksinCat" select= 
       "key('kBookByCat', category)"/> 

     <xsl:value-of select="category"/> : <xsl:text/> 
     <xsl:value-of select="count($vBooksinCat[@isbn=$vMyIsbns])"/> 
     <xsl:text> book(s)&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 

當包含在MyLibrary.xml提供的XML文檔應用:

<library> 
    <book isbn="1"/> 
    <book isbn="3"/> 
    <book isbn="5"/> 
</library> 

並且提供了包含在文件C:\temp\delete\reference.xml中的這個XML文檔:

<reference> 
    <book isbn="1"> 
     <category>SF</category> 
    </book> 
    <book isbn="2"> 
     <category>SF</category> 
    </book> 
    <book isbn="3"> 
     <category>SF</category> 
    </book> 
    <book isbn="4"> 
     <category>Comedy</category> 
    </book> 
    <book isbn="5"> 
     <category>Comedy</category> 
    </book> 
</reference> 

想要的,正確的結果產生

SF : 2 book(s) 
Comedy : 1 book(s) 

II。 XSLT 2.0解決方案:

這稍微簡單一些,因爲我們可以將密鑰定義爲依賴於第二個文檔。

<xsl:stylesheet version="2.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="kBookByCat" match="book[@isbn = $vMyIsbns]" 
      use="category"/> 

    <xsl:variable name="vRef" select= 
    "document('file:///c:/temp/delete/reference.xml')"/> 

    <xsl:variable name="vMyIsbns" select="/*/*/@isbn"/> 

    <xsl:variable name="vResult"> 
     <xsl:apply-templates select="$vRef/*"/> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <xsl:copy-of select="$vResult"/> 
    </xsl:template> 

    <xsl:template match= 
     "book[generate-id() 
      = 
      generate-id(key('kBookByCat', category)[1]) 
      ] 
     "> 
     <xsl:variable name="vBooksinCat" select= 
       "key('kBookByCat', category)"/> 

     <xsl:value-of select="category"/> : <xsl:text/> 
     <xsl:value-of select="count($vBooksinCat)"/> 
     <xsl:text> book(s)&#xA;</xsl:text> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 
+0

絕對是最好的方法和解決方案!非常感謝您的高技能水平。 – Seb

+0

@Seb:不客氣。 –