Search code examples
xsltxslt-1.0xslt-grouping

Grouping when using 2 different XML files as sources?


what i want to do is a typical grouping that can usualy be done using xsl:key, but it become more complicated as data to groups are in 2 differents files. How process ? Here is an example of what i want to do, can i request your help ? must be xslt-1.0 compliant.

bookreference.xml :

<t>  
    <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>
</t>  

mylibrary.xml :

<t>  
   <book isbn="1">
       <price>10</price>
   </book>
   <book isbn="2">
      <price>10</price>
   </book>       
   <book isbn="3">
      <price>20</price>
   </book>
   <book isbn="4">
      <price>5</price>
   </book>
</t>  

output wanted:

SF : 3 book(s) - Total : 40$
Comedy : 2 book(s) - Total : 5$

Solution

  • As already suggested in my comment, you can first merge two documents into a result tree fragment, then use exsl:node-set to get a node-set on which you can then apply Muenchian grouping:

    <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:param name="price-url" select="'test2011113002.xml'"/>
      <xsl:variable name="doc2" select="document($price-url)"/>
    
      <xsl:output method="text"/>
    
      <xsl:variable name="rtf">
        <xsl:apply-templates select="//book" mode="merge"/>
      </xsl:variable>
    
      <xsl:template match="book" mode="merge">
        <xsl:copy>
          <xsl:variable name="isbn" select="@isbn"/>
          <xsl:copy-of select="@* | node()"/>
          <xsl:for-each select="$doc2">
            <xsl:copy-of select="key('k1', $isbn)/price"/>
          </xsl:for-each>
        </xsl:copy>
      </xsl:template>
    
      <xsl:key name="k1" match="book" use="@isbn"/>
      <xsl:key name="k2" match="book" use="category"/>
    
      <xsl:template match="/">
        <xsl:apply-templates select="exsl:node-set($rtf)/book[generate-id() = generate-id(key('k2', category)[1])]"/>
      </xsl:template>
    
      <xsl:template match="book">
        <xsl:variable name="current-group" select="key('k2', category)"/>
        <xsl:value-of select="concat($current-group/category, ': ', count($current-group), ' - Total : ', sum($current-group/price), '&#10;')"/>
      </xsl:template>
    
    </xsl:stylesheet>