Reputation: 23
I'm having a hard time trying to implement an XSL transformation.
I need to transform this:
<records>
<item>
<id type="uid">1</id>
<name>Homepage</name>
<attr>AB308E</attr>
</item>
<item>
<id type="uid">5</id>
<name>Electronics</name>
<attr>F04550</attr>
</item>
<item>
<id type="uid">8</id>
<name>Accessories</name>
<attr>00EE80</attr>
</item>
</records>
into this:
<records>
<item>
<id type="uid">1</id>
<category>Homepage - Electronics - Accessories</category>
<attr>AB308E</attr>
</item>
<item>
<id type="uid">5</id>
<name>Electronics</name>
<attr>F04550</attr>
</item>
<item>
<id type="uid">8</id>
<name>Accessories</name>
<attr>00EE80</attr>
</item>
</records>
I know it doesn't make a lot of sense semantically speaking, but that's a hack I need in order to inject data in a specific manner into some interface.
Rule #1: the name
tag of the first item
of each records
tag (there are many records in the actual file) turns into category
and contains the concatenation of all item's names from the current records
scope
Rule #2: item
tags that are not first child of records
are unchanged.
I tried using <xsl:value-of select="concat(' - ', .)"/>
rules but had no luck.
Would anyone know how to achieve this?
Upvotes: 2
Views: 37
Reputation: 4803
Try this:
<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="records/item[1]/name">
<category>
<xsl:for-each select="../../item/name">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:value-of select="' - '" />
</xsl:if>
</xsl:for-each>
</category>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 167716
Use the identity transformation as the base template and add a template
<xsl:template match="records/item[1]/name">
<category>
<xsl:value-of select="., ../following-sibling::item/name" separator=" - "/>
</category>
</xsl:template>
Upvotes: 1