Reputation: 1
I am relatively new to XLST and this might be a typical beginners problem, but I can't figure it out. Hope you can help and understand me. Thank you in advance. :-)
I try to transform a big XML file to another one, but can't figure out how I can get the first and last node and surround them with other nodes.
The problem is all fruit-nodes are created iteratively.
In my opinion, I should add the surrounding fruits-nodes after all fruit - elements are created.
I already tried something like:
<xsl:template name="tplFruit" match="PARENT_FRUIT">
<xsl:apply-template select="(//element[@name='fruit'])[1]" />
</xsl:template>
<xsl:template name="addFruits">
<fruits>
</xsl:template>
<xsl:template name="tplFruit" match="PARENT_FRUIT">
<xsl:apply-template select="(//element[@name='fruit'])[last()]" />
</xsl:template>
<xsl:template name="addFruits">
</fruits>
</xsl:template>
But it doesn't work and I am pretty sure another error will occur because I open and close the elements fruits in different templates.
The following xml is given (Input - XML):
<root>
... other elements ...
<PARENT_FRUIT>
<different_node nr="1" />
<different_node nr="2" />
<different_node nr="3" />
<fruit>
<name>Apple</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry</name>
<calorien>999</calorien>
<color>red</color></fruit>
<fruit>
<name>banana</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<different_node nr="4" />
<different_node nr="5" />
<different_node nr="6" />
<fruit>
<name>Apple2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>banana2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
...and so on...
</PARENT_FRUIT>
...other elements ...
</root>
The following XML should be my end result:
<root>
... other elements ...
<PARENT_FRUIT>
... other elements ...
<fruits>
<fruit>
<name>apple</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
<fruit>
<name>banana</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
<fruit>
<name>apple2</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry2</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
<fruit>
<name>banana2</name>
<calorien>999</carlorien>
<color>red</color>
</fruit>
... and so on ...
<fruits>
... other elements ...
<PARENT_FRUIT>
... other elements ...
</root>
I use XLST Version 1.0
Upvotes: 0
Views: 300
Reputation: 167516
You can match on fruit[1]
and wrap all fruit
elements into a fruits
container and match on the other fruit
elements to not process them:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="fruit[1]">
<fruits>
<xsl:copy-of select="../fruit"/>
</fruits>
</xsl:template>
<xsl:template match="fruit[position() > 1]"/>
</xsl:stylesheet>
Upvotes: 0
Reputation: 29022
If you can live with all of the other elements grouped at the beginning, the following, simple, XSLT-1.0 stylesheet will do the job. Otherwise it would be unclear where you want to place the <fruits>
element.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="PARENT_FRUIT">
<xsl:copy>
<xsl:apply-templates select="*[not(self::fruit)]|@*"/>
<fruits>
<xsl:apply-templates select="fruit"/>
</fruits>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Its output is:
<?xml version="1.0"?>
<root>
... other elements ...
<PARENT_FRUIT>
<different_node nr="1"/>
<different_node nr="2"/>
<different_node nr="3"/>
<different_node nr="4"/>
<different_node nr="5"/>
<different_node nr="6"/>
<fruits><fruit>
<name>Apple</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>banana</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>Apple2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>cherry2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
<fruit>
<name>banana2</name>
<calorien>999</calorien>
<color>red</color>
</fruit>
</fruits>
</PARENT_FRUIT>
...other elements ...
</root>
Upvotes: 0