I'm new to XSLT, so this is probably very basic, but I would really appreciate some input. I need to transform the child nodes in my xml, but at the same time keep the parent nodes unchanged. My xml looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XMLTest xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:jfxpf="http://www.xfa.com/schema/xml-package" xmlns:xfa="http://www.xfa.com/schema/xfa-data">
<result form="10" version="4" resultid="23146" respondent="ycisxmir" authid="" date="2012-09-12 06:39:44" times="462">
<Q0061 answerid="1">1</Q0061>
<Q0060 answerid="2">2</Q0060>
<QTXT1>1</QTXT1>
</result>
</XMLTest>
I need to keep the two top nodes XMLTest and result unchanged, whereas the child nodes need to be transformed to a more generic format like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<XMLTest xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:jfxpf="http://www.xfa.com/schema/xml-package" xmlns:xfa="http://www.xfa.com/schema/xfa-data">
<result form="10" version="4" resultid="23146" respondent="ycisxmir" authid="" date="2012-09-12 06:39:44" times="462">
<answer>Q0061</answer>
<id>1</id>
<value>1</value>
<answer>Q0060</answer>
<id>2</id>
<value>2</value>
<answer>QTXT1</answer>
<value>1</value>
</result>
</XMLTest>
My xslt so far looks like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="result/*">
<answer><xsl:value-of select="local-name()"/></answer>
<id><xsl:value-of select="@answerid"/></id>
<value><xsl:value-of select="@*"/></value>
</xsl:template>
</xsl:stylesheet>
I've tried using xsl:copy on the top nodes, but can't make it work without losing the child nodes, or the transformation of the child nodes. How can I keep the top nodes and force through my transformed child nodes at the same time?
Start with
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
Now add templates for the transformation you need i.e.
<xsl:template match="result/*[@answerid]">
<answer><xsl:value-of select="local-name()"/></answer>
<id><xsl:value-of select="@answerid"/></id>
<value><xsl:value-of select="."/></value>
</xsl:template>
<xsl:template match="result/*[not(@answerid)]">
<answer><xsl:value-of select="local-name()"/></answer>
<value><xsl:value-of select="."/></value>
</xsl:template>
You are missing Identity template:
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
I have corrected you answer..:
<?xml version="1.0" encoding="utf-8"?>
<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="/XMLTest/result/*">
<answer>
<xsl:value-of select="local-name()"/>
</answer>
<id>
<xsl:value-of select="@answerid"/>
</id>
<value>
<xsl:value-of select="@*"/>
</value>
</xsl:template>
</xsl:stylesheet>
Edit1: updated template to discard if attributes are null: an if condition checks if attribute is null before converting it to an element..
<xsl:template match="/XMLTest/result/*">
<answer>
<xsl:value-of select="local-name()"/>
</answer>
<xsl:if test="@answerid/.!=''">
<id>
<xsl:value-of select="@answerid"/>
</id>
</xsl:if>
<xsl:if test="@*/.!=''">
<value>
<xsl:value-of select="@*"/>
</value>
</xsl:if>
</xsl:template>
Edit2: in ur early attempts, you were trying to copy value of @*, @*
indicates Attribute of anyname, so it was copying value of @answerid (since that was the only attribute available).. what you had to do is .. valu-of="."
.. please try the below code..
<xsl:template match="/XMLTest/result/*">
<answer>
<xsl:value-of select="local-name()"/>
</answer>
<xsl:if test="@answerid/.!=''">
<id>
<xsl:value-of select="@answerid"/>
</id>
</xsl:if>
<xsl:if test=".!=''">
<value>
<xsl:value-of select="."/>
</value>
</xsl:if>
</xsl:template>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With