Reputation: 15
I want to transform a simple xml using xsl. I know there are many examples on this site, but if anyone can help me go to the next step.
This is the source xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<output>
<cars>
<car>
<id>1</id>
<brand>Audi</brand>
<type>A3</type>
<license>TST</license>
</car>
</cars>
<distances>
<distance>
<id_car>1</id_car>
<date>20110901</date>
<distance>111</distance>
</distance>
<distance>
<id_car>1</id_car>
<date>20110902</date>
<distance>23</distance>
</distance>
<distance>
<id_car>1</id_car>
<date>20110903</date>
<distance>10</distance>
</distance>
</distances>
</output>
XSL result will be this (results) :
<?xml version="1.0" encoding="ISO-8859-1"?>
<output>
<cars>
<car>
<id>1</id>
<brand>Audi</brand>
<type>A3</type>
<license>TST</license>
<distances>
<distance day="20110901">111</distance>
<distance day="20110902">23</distance>
<distance day="20110903">10</distance>
</distances>
</car>
</cars>
Tthis is the last xsl. Something is missing, because it does not work.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="Dist_car" match="distances/distance" use="id_car" />
<xsl:template match="car">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<distances>
<xsl:apply-templates select="key('Dist_car', id)"/>
</distances>
</xsl:copy>
</xsl:template>
<xsl:template match="distances">
<distance day="{date}"><xsl:value-of select="distance"/></distance>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 137
Reputation: 122414
Start by defining a key to map a car ID to its set of distance
elements
<xsl:key name="distancesForCar" match="distances/distance" use="id_car" />
Now when you are processing a particular car
element you can extract the matching distance
elements using key('distancesForCar', id)
.
For the main structure of the stylesheet I would recommend you start with an identity template (there are many many examples of this on Stack Overflow) which copies the input to output unchanged. Next you add specific templates to ignore the distances
element
<xsl:template match="distances"/>
and to append the required <distance day="...">...</distance>
elements to the end of each car
<xsl:template match="car">
<!-- copy as the identity template would -->
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<!-- but add distances before the end tag -->
<distances>
<xsl:apply-templates select="key('distancesForCar', id)"/>
</distances>
</xsl:copy>
</xsl:template>
<xsl:template match="distance">
<distance day="{date}">
<xsl:value-of select="distance"/>
</distance>
</xsl:template>
Upvotes: 2