Reputation: 23
I'm stumped and am very new to XSLT. A little direciton would be greatly appreciated. My ultimate objective is to bring the firstName, lastName, and gender elements under the student element up into that element as attributes, but also want to retain the StudentID attribute that already exists there. I'd also like that "year_Collection" to disappear.
I started with this XML document
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student StudentID="123456">
<firstName firstName="John"/>
<lastName lastName="Johnson"/>
<gender gender="M"/>
<year_Collection>
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</year_Collection>
</student>
</Report>
My desired output looks like this
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student gender="M" lastName="Johnson" firstName="John" StudentID="123456">
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</student>
</Report>
I was able to use this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:r="Upload" exclude-result-prefixes="r" extension-element-prefixes="r">
<xsl:template match="r:student">
<xsl:copy>
<xsl:for-each select="*">
<xsl:attribute name="{local-name(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
To get here:
<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="Upload" Name="Upload">
<student year_Collection="" gender="M" lastName="Johnson" firstName="John">
<year value="2013">
<term hoursEarned="18.00" hoursAttempted="18.00" termCode="S1"/>
</year>
</student>
</Report>
But it overwrites the StudentID attribute that already exists. How do I get the elements to come up as attributes, but not overwrite StudentID?
Also, that pesky year_collection element won't disappear with this, but I can split that into a separate question if that's a better way to go about it.
<xsl:template match="r:year_Collection">
<xsl:apply-templates/>
</xsl:template>
Upvotes: 1
Views: 616
Reputation: 117100
But it overwrites the StudentID attribute that already exists.
No, it doesn't. The problem is you're not copying it. You should start your template with:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="@StudentID"/>
or, if you prefer:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="@*"/>
to copy any and all attributes the Student has.
Regarding the problem with<year_Collection>
, you should try to turn only leaf nodes into attributes, for example:
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="*/@*"/>
<xsl:copy-of select="*/*[@*]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Of course, if your structure is known, naming the required nodes explicitly would be much better, e.g;
<xsl:template match="r:student">
<xsl:copy>
<xsl:copy-of select="@StudentID | r:firstName/@firstName | r:lastName/@lastName | r:gender/@gender"/>
<xsl:copy-of select="r:year_Collection/r:year"/>
</xsl:copy>
</xsl:template>
Upvotes: 1