Reputation: 69
I have an issue where there is no useful tags associated with some data, the data is included at the head of the document, but I can not get this to look how I want.
I've had the Column1 text replacing the tags, but as they are all labelled , it doesn't help much. I'm slowly learning how XSLTs work, but this is beyond my knowledge.
Any assistance would be appreciated.
Input data
<results>
<header>
<a>Column 1 Customer Name</a>
<a>Column 2 Customer Add</a>
<a>Column3</a>
<a>Column4</a>
</header>
<body>
<line>
<a>Data1</a>
<a>Data2</a>
<a>Data3</a>
<a>Data4</a>
</line>
<line>
<a>Data1</a>
<a>Data2</a>
<a>Data3</a>
<a>Data4</a>
</line>
</body>
</results>
>
Required XML
<?xml version="1.0"?>
<results>
<header>
<a>Column 1 Customer Name</a>
<a>Column 2 Customer Add</a>
<a>Column3</a>
<a>Column4</a>
</header>
<body>
<line>
<Column1CustomerName>Data1</Column1CustomerName>
<Column2CustomerAdd>Data2</Column2CustomerAdd>
<Column3>Data3</Column3>
<Column4>Data4</Column4>
</line>
<line>
<Column1CustomerName>Data1</Column1CustomerName>
<Column2CustomerAdd>Data2</Column2CustomerAdd>
<Column3>Data3</Column3>
<Column4>Data4</Column4>
</line>
</body>
</results>
Following on from a users response, I have implemented the following XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/results">
<results>
<xsl:copy-of select="header"/>
<body>
<xsl:for-each select="body/line">
<line>
<xsl:for-each select="a">
<xsl:variable name="index" select="position()" />
<xsl:element name="{//header/a[$index]}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</line>
</xsl:for-each>
</body>
</results>
</xsl:template>
</xsl:stylesheet>
My problem now is if a header contains a space, as this causes the style sheet to try and create an XML tag with a space in.
I've tried using the replace function, which has been suggested.
<xsl:element name="{replace(//cols/c[$index],' ','')}">
And I seem to be getting this wrong, or calling this in the wrong place.
Thanks for everyone's input.
Upvotes: 1
Views: 1207
Reputation: 6741
You need <xsl:element>
to do the trick.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/results">
<results>
<xsl:copy-of select="header"/>
<body>
<xsl:for-each select="body/line">
<line>
<xsl:for-each select="a">
<xsl:variable name="index" select="position()" />
<xsl:element name="{replace(//header/a[$index], ' ', '')}">
<xsl:value-of select="." />
</xsl:element>
</xsl:for-each>
</line>
</xsl:for-each>
</body>
</results>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2
Reputation: 3738
Here's a completely "push-oriented" (focuses on usage of <xsl:template>
and <xsl:apply-templates>
, doesn't explicitly pull data with elements such as <xsl:value-of>
, etc.) solution that doesn't use <xsl:for-each>
.
When this XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="line/a">
<xsl:variable name="vPos" select="position()" />
<xsl:element name="{/*/header/a[$vPos]}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
...is applied to the provided XML:
<results>
<header>
<a>Column1</a>
<a>Column2</a>
<a>Column3</a>
<a>Column4</a>
</header>
<body>
<line>
<a>Data1</a>
<a>Data2</a>
<a>Data3</a>
<a>Data4</a>
</line>
<line>
<a>Data1</a>
<a>Data2</a>
<a>Data3</a>
<a>Data4</a>
</line>
</body>
</results>
...the wanted answer is produced:
<?xml version="1.0"?>
<results>
<header>
<a>Column1</a>
<a>Column2</a>
<a>Column3</a>
<a>Column4</a>
</header>
<body>
<line>
<Column1>Data1</Column1>
<Column2>Data2</Column2>
<Column3>Data3</Column3>
<Column4>Data4</Column4>
</line>
<line>
<Column1>Data1</Column1>
<Column2>Data2</Column2>
<Column3>Data3</Column3>
<Column4>Data4</Column4>
</line>
</body>
</results>
Upvotes: 1