Help on xslt - grouping

P

Per Jørgen Vigdal

I have a XML that I need to map.
The XML goes like:

<Children>
<Child>
<References>
<External>
<Reference name="filename" value="1.dat"/>
<Reference name="invoicenr" value="1111111"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="2.dat"/>
<Reference name="invoicenr" value="222222"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="3.dat"/>
<Reference name="invoicenr" value="33333"/>
<Reference name="invoicer_name" value="Clinton"/>
<Reference name="invoiceref" value="ccccc"/>
</External>
</References>
</Child>
</Children>

I want the structure to map to:

<Senders>
<Sender>
<invoicer_name>Bill</invoicer_name>
<invoiceref>bbbbbb</invoiceref>
<Items TotalItems="2"/>
</Sender>
<Sender>
<invoicer_name>Clinton</invoicer_name>
<invoiceref>ccccc</invoiceref>
<Items TotalItems="1"/>
</Sender>
</Senders>

I have tried to use the "Muenchian Grouping" method, but am not able to
obtain both
<invoicer_name> and <invoiceref> under the <Sender> tag

Here is my xsl :

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:eek:utput encoding="ISO-8859-1"/>
<xsl:key name="kDistinctSender"
match="Children/Child/References/External/Reference[@name='invoicer_name']/@
value" use="."/>
<xsl:template match="/">
<Senders>
<!-- go through distinct InvoicerName -->
<xsl:for-each
select="/Children/Child/References/External/Reference[@name='invoicer_name']
/@value[generate-id()=generate-id(key('kDistinctSender',.))]">
<!-- sort by InvoicerName -->
<xsl:sort select="."/>
<Sender>
<xsl:variable name="InvoicerName">
<xsl:value-of select="."/>
</xsl:variable>
<InvoicerName>
<xsl:value-of select="$InvoicerName"/>
</InvoicerName>
<Items TotalItems="{count(key('kDistinctSender',.))}">
</Items>
</Sender>
</xsl:for-each>
</Senders>
</xsl:template>
</xsl:stylesheet>
 
D

Dimitre Novatchev

Specify for the "use" attribute of xsl:key the concatenation of the values
of "invoicer_name" and "invoiceref".


Cheers,
Dimitre Novatchev
 
P

Per Jørgen Vigdal

Thanks
I have tried to play around with concatenation and cant get it right, her is
the result :

<Senders>
<Sender>
<InvoicerName>Bill</InvoicerName>
<Items TotalItems="3"/>
</Sender>
</Senders>


Using xsl :

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:eek:utput encoding="ISO-8859-1"/>
<xsl:key name="kDistinctSender"
match="Children/Child/References/External/Reference[@name='invoicer_name']/@
value" use="concat(@name,'||',@value)"/>
<xsl:template match="/">
<Senders>

<xsl:for-each
select="/Children/Child/References/External/Reference[@name='invoicer_name']
/@value[generate-id()=generate-id(key('kDistinctSender',concat(@name,'||',@v
alue)))]">

<xsl:sort select="."/>
<Sender>
<xsl:variable name="InvoicerName">
<xsl:value-of select="."/>
</xsl:variable>
<InvoicerName>
<xsl:value-of select="$InvoicerName"/>
</InvoicerName>
<Items
TotalItems="{count(key('kDistinctSender',concat(@name,'||',@value)))}">
</Items>
</Sender>
</xsl:for-each>
</Senders>
</xsl:template>
</xsl:stylesheet>
Dimitre Novatchev said:
Specify for the "use" attribute of xsl:key the concatenation of the values
of "invoicer_name" and "invoiceref".


Cheers,
Dimitre Novatchev


Per Jørgen Vigdal said:
I have a XML that I need to map.
The XML goes like:

<Children>
<Child>
<References>
<External>
<Reference name="filename" value="1.dat"/>
<Reference name="invoicenr" value="1111111"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="2.dat"/>
<Reference name="invoicenr" value="222222"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="3.dat"/>
<Reference name="invoicenr" value="33333"/>
<Reference name="invoicer_name" value="Clinton"/>
<Reference name="invoiceref" value="ccccc"/>
</External>
</References>
</Child>
</Children>

I want the structure to map to:

<Senders>
<Sender>
<invoicer_name>Bill</invoicer_name>
<invoiceref>bbbbbb</invoiceref>
<Items TotalItems="2"/>
</Sender>
<Sender>
<invoicer_name>Clinton</invoicer_name>
<invoiceref>ccccc</invoiceref>
<Items TotalItems="1"/>
</Sender>
</Senders>

I have tried to use the "Muenchian Grouping" method, but am not able to
obtain both
<invoicer_name> and <invoiceref> under the <Sender> tag

Here is my xsl :

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:eek:utput encoding="ISO-8859-1"/>
<xsl:key name="kDistinctSender"
match="Children/Child/References/External/Reference[@name='invoicer_name']/@
value" use="."/>
<xsl:template match="/">
<Senders>
<!-- go through distinct InvoicerName -->
<xsl:for-each
select="/Children/Child/References/External/Reference[@name='invoicer_name']
/@value[generate-id()=generate-id(key('kDistinctSender',.))]">
<!-- sort by InvoicerName -->
<xsl:sort select="."/>
<Sender>
<xsl:variable name="InvoicerName">
<xsl:value-of select="."/>
</xsl:variable>
<InvoicerName>
<xsl:value-of select="$InvoicerName"/>
</InvoicerName>
<Items TotalItems="{count(key('kDistinctSender',.))}">
</Items>
</Sender>
</xsl:for-each>
</Senders>
</xsl:template>
</xsl:stylesheet>
 
V

Volkm@r

Per said:
I have a XML that I need to map.
The XML goes like:

<Children>
<Child>
<References>
<External>
<Reference name="filename" value="1.dat"/>
<Reference name="invoicenr" value="1111111"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="2.dat"/>
<Reference name="invoicenr" value="222222"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="3.dat"/>
<Reference name="invoicenr" value="33333"/>
<Reference name="invoicer_name" value="Clinton"/>
<Reference name="invoiceref" value="ccccc"/>
</External>
</References>
</Child>
</Children>

I want the structure to map to:

<Senders>
<Sender>
<invoicer_name>Bill</invoicer_name>
<invoiceref>bbbbbb</invoiceref>
<Items TotalItems="2"/>
</Sender>
<Sender>
<invoicer_name>Clinton</invoicer_name>
<invoiceref>ccccc</invoiceref>
<Items TotalItems="1"/>
</Sender>
</Senders>

I have tried to use the "Muenchian Grouping" method, but am not able to
obtain both
<invoicer_name> and <invoiceref> under the <Sender> tag

Here is my xsl :

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput method="xml" indent="yes"/>
<xsl:eek:utput encoding="ISO-8859-1"/>
<xsl:key name="kDistinctSender"
match="Children/Child/References/External/Reference[@name='invoicer_name']/@
value" use="."/>
<xsl:template match="/">
<Senders>
<!-- go through distinct InvoicerName -->
<xsl:for-each
select="/Children/Child/References/External/Reference[@name='invoicer_name']
/@value[generate-id()=generate-id(key('kDistinctSender',.))]">
<!-- sort by InvoicerName -->
<xsl:sort select="."/>
<Sender>
<xsl:variable name="InvoicerName">
<xsl:value-of select="."/>
</xsl:variable>
<InvoicerName>
<xsl:value-of select="$InvoicerName"/>
</InvoicerName>
<Items TotalItems="{count(key('kDistinctSender',.))}">
</Items>
</Sender>
</xsl:for-each>
</Senders>
</xsl:template>
</xsl:stylesheet>

Did you try to simply put them in the right order?


<xsl:template match="/">
<Senders>
<!-- go through distinct InvoicerName -->
<xsl:apply-templates select="-XPath expression-">
</Senders>
</xsl:template>

<xsl:template match="-expression from above-">
<Sender>
<xsl:apply-templates select=".[@name='invoicer_name']"/>
<xsl:apply-templates select=".[@name='invoiceref']"/>
<xsl:apply-templates select=".[@name='otherArtributeName']"/>
<xsl:apply-templates select=".[@name='............']"/>
<xsl:apply-templates select=".[@name='-one more line-']"/>
</Sender>
</xsl:apply-templates>
</xsl:template>

<xsl:........... - And Some More Templates - ........./>
 
D

Dimitre Novatchev

Per Jørgen Vigdal said:
Thanks
I have tried to play around with concatenation and cant get it right, her
is
the result :

<Senders>
<Sender>
<InvoicerName>Bill</InvoicerName>
<Items TotalItems="3"/>
</Sender>
</Senders>


This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:key name="kExtNameRef" match="External"
use="concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)"/>
<xsl:template match="/">
<Senders>
<xsl:for-each select=
"/*/*/*/External
[generate-id()
=
generate-id(
key('kExtNameRef',
concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)
)[1]
)
]">
<Sender>
<invoicer_name>
<xsl:value-of select=
"Reference[@name='invoicer_name']/@value"/>
</invoicer_name>
<invoiceref>
<xsl:value-of select=
"Reference[@name='invoiceref']/@value"/>
</invoiceref>
<Items TotalItems="{
count(
key('kExtNameRef',
concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)
)
)
}"/>
</Sender>
</xsl:for-each>
</Senders>

</xsl:template>
</xsl:stylesheet>

when applied on your source.xml:

<Children>
<Child>
<References>
<External>
<Reference name="filename" value="1.dat"/>
<Reference name="invoicenr" value="1111111"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="2.dat"/>
<Reference name="invoicenr" value="222222"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="3.dat"/>
<Reference name="invoicenr" value="33333"/>
<Reference name="invoicer_name" value="Clinton"/>
<Reference name="invoiceref" value="ccccc"/>
</External>
</References>
</Child>
</Children>

produces the wanted result:

<Senders>
<Sender>
<invoicer_name>Bill</invoicer_name>
<invoiceref>bbbbbb</invoiceref>
<Items TotalItems="2" />
</Sender>
<Sender>
<invoicer_name>Clinton</invoicer_name>
<invoiceref>ccccc</invoiceref>
<Items TotalItems="1" />
</Sender>
</Senders>


Hope this helped.

Cheers,
Dimitre Novatchev
 
P

Per Jørgen Vigdal

This is great, exactly what I want. Thank you.
This is goanna be tested in QA 22. Mai and if successful, put into
production on 25. Mai where the
xsl will do transformation on files that are as big as 100MB with thousands
of items






Dimitre Novatchev said:
Per Jørgen Vigdal said:
Thanks
I have tried to play around with concatenation and cant get it right, her
is
the result :

<Senders>
<Sender>
<InvoicerName>Bill</InvoicerName>
<Items TotalItems="3"/>
</Sender>
</Senders>


This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:eek:utput omit-xml-declaration="yes" indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:key name="kExtNameRef" match="External"
use="concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)"/>
<xsl:template match="/">
<Senders>
<xsl:for-each select=
"/*/*/*/External
[generate-id()
=
generate-id(
key('kExtNameRef',
concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)
)[1]
)
]">
<Sender>
<invoicer_name>
<xsl:value-of select=
"Reference[@name='invoicer_name']/@value"/>
</invoicer_name>
<invoiceref>
<xsl:value-of select=
"Reference[@name='invoiceref']/@value"/>
</invoiceref>
<Items TotalItems="{
count(
key('kExtNameRef',
concat(Reference[@name='invoicer_name']/@value,
'+',
Reference[@name='invoiceref']/@value
)
)
)
}"/>
</Sender>
</xsl:for-each>
</Senders>

</xsl:template>
</xsl:stylesheet>

when applied on your source.xml:

<Children>
<Child>
<References>
<External>
<Reference name="filename" value="1.dat"/>
<Reference name="invoicenr" value="1111111"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="2.dat"/>
<Reference name="invoicenr" value="222222"/>
<Reference name="invoicer_name" value="Bill"/>
<Reference name="invoiceref" value="bbbbbb"/>
</External>
</References>
</Child>
<Child>
<References>
<External>
<Reference name="filename" value="3.dat"/>
<Reference name="invoicenr" value="33333"/>
<Reference name="invoicer_name" value="Clinton"/>
<Reference name="invoiceref" value="ccccc"/>
</External>
</References>
</Child>
</Children>

produces the wanted result:

<Senders>
<Sender>
<invoicer_name>Bill</invoicer_name>
<invoiceref>bbbbbb</invoiceref>
<Items TotalItems="2" />
</Sender>
<Sender>
<invoicer_name>Clinton</invoicer_name>
<invoiceref>ccccc</invoiceref>
<Items TotalItems="1" />
</Sender>
</Senders>


Hope this helped.

Cheers,
Dimitre Novatchev
 
D

Dimitre Novatchev

Per Jørgen Vigdal said:
This is great, exactly what I want. Thank you.
This is goanna be tested in QA 22. Mai and if successful, put into
production on 25. Mai where the
xsl will do transformation on files that are as big as 100MB with
thousands
of items

Good luck, and it would be interesting if you share your experience (or if
you have any problems -- just signal) to the newsgroups (and the xsl-list).


Cheers,
Dimitre Novatchev
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top