I have the following XML documents:
Doc 1
<root>
<headers>
<heading>Photo</heading>
<heading>Number</heading>
<heading>Month Taken</heading>
<heading>Description</heading>
</headers>
<data>
<item>
<elm1>Cats</elm1>
<elm2>001</elm2>
<elm3>August</elm3>
<elm4>Cats playing in house</elm4>
</item>
<item>
<elm1>Winter</elm1>
<elm2>002</elm2>
<elm3></elm3>
<elm4>Snow covered trees during winter</elm4>
</item>
</data>
</root>
I want to output XML that uses the "headers" piece of the XML to name the elements within the "data," like so.
Ideal output
<data>
<item>
<Photo>Cats</Photo>
<Number>001</Number>
<Month_Taken>August</Month_Taken>
<Description>Cats playing in house</Description>
</item>
<item>
<Photo>Winter</Photo>
<Number>002</Number>
<Month_Taken></Month_Taken>
<Description>Snow covered trees during winter</Description>
</item>
</data>
How would I achieve this? A for loop seems awkward within XSL. I tried to use "position()" but this seemed to have similar issues. Is there an easy way to substitute element names within XSL?
CodePudding user response:
How about:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<data>
<xsl:variable name="col" select="headers/heading" />
<xsl:for-each select="data/item">
<item>
<xsl:for-each select="*">
<xsl:variable name="i" select="position()" />
<xsl:element name="{translate($col[$i], ' ', '_')}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</item>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
Do note that merely replacing spaces with underscores does not ensure that the result is a valid element name.