I have an XML file here:
<?xml version="1.0" encoding="utf-16"?>
<class>
<student>
<name>Ben</name>
<age>1</age>
<ages>4</ages>
<entryprofile></entryprofile>
<node>1</node>
</student>
<student>
<name>Steve</name>
<age>2</age>
<ages>3</ages>
<entryprofile></entryprofile>
<node>1</node>
</student>
</class>
I am trying to promote the entryprofile
element so that it becomes a child element of student
, rather than an attribute of student
--and I want it to contain node
. I have tried to apply the following XSL in order to do this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="student">
<xsl:copy-of select="name"/>
<new-level>
<xsl:copy-of select="entryprofile"/>
</new-level>
</xsl:template>
</xsl:stylesheet>
This doesn't seem to be doing much apart from this:
<?xml version="1.0" encoding="utf-16"?>
<name>Ben</name><new-level><entryprofile>g</entryprofile></new-level>
<name>Steve</name><new-level><entryprofile>g</entryprofile></new-level>
But what I am looking for is this:
<?xml version="1.0" encoding="utf-16"?>
<class>
<student>
<name>Ben</name>
<age>1</age>
<ages>4</ages>
<entryprofile>
<node>1</node>
</entryprofile>
</student>
<student>
<name>Steve</name>
<age>2</age>
<ages>3</ages>
<entryprofile>
<node>1</node>
</entryprofile>
</student>
</class>
You can see there that entryprofile
for both stdudents has become a child on account of node
becoming a child of entryprofile
.
Would anyone know where I am going wrong, and what I can do to achieve my desired result? Many thanks.
CodePudding user response:
This XSLT will produce the desired result:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entryprofile">
<xsl:copy>
<xsl:copy-of select="../node"/>
</xsl:copy>
</xsl:template>
<xsl:template match="node"/>
</xsl:stylesheet>
CodePudding user response:
Here are two alternatives that accomplish the same thing in slightly different ways:
This one is the correct version of what you tried to do:
<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:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="student">
<xsl:copy>
<xsl:copy-of select="name | age | ages | profile"/>
<entryprofile>
<xsl:copy-of select="node"/>
</entryprofile>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This one is a shorter version of the above:
<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="/class">
<xsl:copy>
<xsl:for-each select="student">
<xsl:copy>
<xsl:copy-of select="name | age | ages | profile"/>
<entryprofile>
<xsl:copy-of select="node"/>
</entryprofile>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>