tags:

views:

44

answers:

2

I have two xml data sources like this:

<orders>
 <order>
  <ordernumber>123</ordernumber>
  <subtotal>20</subtotal>
  <total>23.5</total>
 </order>
  <order>
  <ordernumber>234</ordernumber>
  <subtotal>19</subtotal>
  <total>26.5</total>
 </order>
</orders>

<orderitems>
 <item>
  <ordernumber>123</ordernumber>
  <productname>test1</productname>
  <sku>s9sdidk</sku>
 <item>
 <item>
  <ordernumber>123</ordernumber>
  <productname>test2</productname>
  <sku>123232</sku>
 <item>
 <item>
  <ordernumber>234</ordernumber>
  <productname>test3</productname>
  <sku>s9sd2d32k</sku>
 <item>
 <item>
  <ordernumber>234</ordernumber>
  <productname>test4</productname>
  <sku>s9swe23</sku>
 <item>
</orderitems>

and then I need to use xslt to group items by order number and get an output like this:

productname               sku
test1                     s9sdidk
test2                     123232
---------------------------------
   subtotal: 20
   total: 23.5

productname               sku
test3                     s9sd2d32k
test4                     s9swe23
---------------------------------
   subtotal: 19
   total: 26.5

I need to use html tags so I can't use for-each-group thing...please help! thanks in advance.

A: 

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output method="text"/>
    <xsl:key name="kItemByOrdernumber" match="item" use="ordernumber"/>
    <xsl:variable name="vSource2" select="document('source2.xml')"/>
    <xsl:template match="text()"/>
    <xsl:template match="order/ordernumber">
        <xsl:variable name="vCurrent" select="."/>
        <xsl:text>productname&#x9;&#x9;sku&#xA;</xsl:text>
        <xsl:for-each select="$vSource2">
            <xsl:apply-templates
                     select="key('kItemByOrdernumber',$vCurrent)"/>
        </xsl:for-each>
        <xsl:value-of 
             select="concat('---------------------------------','&#xA;',
                            '&#x9;subtotal: ',../subtotal,'&#xA;',
                            '&#x9;total: ',../total,'&#xA;&#xA;')"/>
    </xsl:template>
    <xsl:template match="item">
        <xsl:value-of select="concat(productname,'&#x9;&#x9;&#x9;',
                                     sku,'&#xA;')"/>
    </xsl:template>
</xsl:stylesheet>

With first document as input and second document as source2.xml external input, output:

productname     sku
test1           s9sdidk
test2           123232
---------------------------------
    subtotal: 20
    total: 23.5

productname     sku
test3           s9sd2d32k
test4           s9swe23
---------------------------------
    subtotal: 19
    total: 26.5
Alejandro
Thank you so much Alejandro! I will try that and keep you posted.
Fei
Actually what I am really trying to do is:
Fei
I am pretty new to xslt, sorry for the confusion i caused and may waste your time...Actually what I am really trying to do is: I have two queries, first query (orders/order) <query name="orders" rowElementName="order"> select ordernumber, subtotal, total from tablex</query>return something like:ordernumber subtotal total123 20 23.5234 19 26.5
Fei
another query (orderitems/lineitem)<query name="OrderItems" rowElementName="lineitem"> select ordernumber, cartitemid, productname, sku from tabley</query>return something like:ordernumber cartitemid productname sku123 3 test1 s9sdidk123 4 test2 s9sdidl234 5 test3 s9sdidu234 6 test4 s9sdidh
Fei
huhhh...I'd better start a new post...
Fei
@Fei: No problem. Just do that.
Alejandro
OK, finally got it all worked. Thank you so much Alejandro and Dimitre!
Fei
A: 

This transformation:

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

 <xsl:key name="kitemByOrder" match="item" use="ordernumber"/>

 <xsl:param name="pmaxSize" select="100"/>

 <xsl:template match="*">
  <xsl:apply-templates />
 </xsl:template>

 <xsl:template match="order">
productname<xsl:text>&#9;</xsl:text>sku
<xsl:apply-templates select="key('kitemByOrder', ordernumber)"/>
 ---------------------------------
   subtotal: <xsl:value-of select="subtotal"/>
   total: <xsl:value-of select="total"/>
   <xsl:text>&#xA;&#xA;</xsl:text>
 </xsl:template>

 <xsl:template match="item">
  <xsl:value-of select="concat(productname, '&#9;&#9;', sku, '&#xA;')"/>
 </xsl:template>

 <xsl:template match="orderitems"/>
</xsl:stylesheet>

when applied on the provided XML document (corrected as it was severely non-well-formed):

<t>
    <orders>
        <order>
            <ordernumber>123</ordernumber>
            <subtotal>20</subtotal>
            <total>23.5</total>
        </order>
        <order>
            <ordernumber>234</ordernumber>
            <subtotal>19</subtotal>
            <total>26.5</total>
        </order>
    </orders>
    <orderitems>
        <item>
            <ordernumber>123</ordernumber>
            <productname>test1</productname>
            <sku>s9sdidk</sku>
        </item>
        <item>
            <ordernumber>123</ordernumber>
            <productname>test2</productname>
            <sku>123232</sku>
        </item>
        <item>
            <ordernumber>234</ordernumber>
            <productname>test3</productname>
            <sku>s9sd2d32k</sku>
        </item>
        <item>
            <ordernumber>234</ordernumber>
            <productname>test4</productname>
            <sku>s9swe23</sku>
        </item>
    </orderitems>
</t>

produces the wanted, correct result:

productname sku
test1       s9sdidk
test2       123232

 ---------------------------------
   subtotal: 20
   total: 23.5


productname sku
test3       s9sd2d32k
test4       s9swe23

 ---------------------------------
   subtotal: 19
   total: 26.5

Note: You may use two different XML documents for the two data sources, but the processing is essentially the same, with the exception that you need to address one of them using the document() function.

Dimitre Novatchev
Hi, Dimitre, thank you so much for the answer. one thing i don't understand is which template is for <xsl:apply-templates select="key('kitemByOrder', ordernumber)"/>? how come it knows should use <xsl:template match="item"> template? thanks.
Fei
sorry, got it...from the key...thanks.
Fei
@Fei: `<xsl:apply-templates select="some-node-set"/>` may apply many different templates for the different nodes contained in `some-node-set`. For each individual node the XSLT processor dynamically decides which is the best-matching template available. In this specific case the result of the `key()` function is a set of `item` elements and we have a template matching `item` -- this is selected by the XSLT processor.
Dimitre Novatchev
what could be wrong if it didn't go to the item template? thanks.
Fei