Reputation: 195
I'm trying to transform (flatten) XML with multiple output using XSLT into XML with single output. But node which must be duplicated for each node is ignored. XML file has two outputs: HEAD and EXPERIMENT.
Source XML document:
<?xml version="1.0" encoding="utf-8"?>
<ELEMENT>
<HEAD>
<FIRSTNAME>Anton</FIRSTNAME>
<SURNAME>Konchik</SURNAME>
<REPORTDATE>01.01.2019</REPORTDATE>
</HEAD>
<EXPERIMENT>
<NAME>EXPERIMENT1</NAME>
<DATE>01.01.2018</DATE>
<RESULT>POSITIVE</RESULT>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT2</NAME>
<DATE>01.01.2019</DATE>
<RESULT>NEGATIVE</RESULT>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT3</NAME>
<DATE>01.01.2017</DATE>
<RESULT>NOTSURE</RESULT>
</EXPERIMENT>
</ELEMENT>
By using code below I want to duplicate HEAD node inside each EXPERIMENT node. XSLT transformation code:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" version="2.0" encoding="UTF-8" />
<xsl:template match="/">
<xsl:element name="ELEMENT">
<xsl:for-each select="ELEMENT/EXPERIMENT">
<xsl:element name="EXPERIMENT">
<xsl:element name="NAME">
<xsl:value-of select="./NAME"/>
</xsl:element>
<xsl:element name="DATE">
<xsl:value-of select="./DATE"/>
</xsl:element>
<xsl:element name="RESULT">
<xsl:value-of select="./RESULT"/>
</xsl:element>
<xsl:for-each select="ELEMENT/HEAD">
<xsl:element name="FIRSTNAME">
<xsl:value-of select="./FIRSTNAME"/>
</xsl:element>
<xsl:element name="SURNAME">
<xsl:value-of select="./SURNAME"/>
</xsl:element>
<xsl:element name="REPORTDATE">
<xsl:value-of select="./REPORTDATE"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Excepted result:
<?xml version="1.0" encoding="utf-8"?>
<ELEMENT>
<EXPERIMENT>
<NAME>EXPERIMENT1</NAME>
<DATE>01.01.2018</DATE>
<RESULT>POSITIVE</RESULT>
<FIRSTNAME>Anton</FIRSTNAME>
<SURNAME>Konchik</SURNAME>
<REPORTDATE>01.01.2019</REPORTDATE>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT2</NAME>
<DATE>01.01.2019</DATE>
<RESULT>NEGATIVE</RESULT>
<FIRSTNAME>Anton</FIRSTNAME>
<SURNAME>Konchik</SURNAME>
<REPORTDATE>01.01.2019</REPORTDATE>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT3</NAME>
<DATE>01.01.2017</DATE>
<RESULT>NOTSURE</RESULT>
<FIRSTNAME>Anton</FIRSTNAME>
<SURNAME>Konchik</SURNAME>
<REPORTDATE>01.01.2019</REPORTDATE>
</EXPERIMENT>
</ELEMENT>
But HEAD node is ignored. Actual result:
<?xml version="1.0" encoding="utf-8"?>
<ELEMENT>
<EXPERIMENT>
<NAME>EXPERIMENT1</NAME>
<DATE>01.01.2018</DATE>
<RESULT>POSITIVE</RESULT>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT2</NAME>
<DATE>01.01.2019</DATE>
<RESULT>NEGATIVE</RESULT>
</EXPERIMENT>
<EXPERIMENT>
<NAME>EXPERIMENT3</NAME>
<DATE>01.01.2017</DATE>
<RESULT>NOTSURE</RESULT>
</EXPERIMENT>
</ELEMENT>
Thanks for your help.
Upvotes: 0
Views: 71
Reputation: 116992
Change:
<xsl:for-each select="ELEMENT/HEAD">
to:
<xsl:for-each select="/ELEMENT/HEAD">
or:
<xsl:for-each select="../HEAD">
What you have is looking for ELEMENT
that is a child of the current EXPERIMENT
. What you need is to start at the root of the tree, or go up in the hierarchy.
Note also that you could do simply:
<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="*"/>
<xsl:template match="/ELEMENT">
<xsl:copy>
<xsl:for-each select="EXPERIMENT">
<xsl:copy>
<xsl:copy-of select="*"/>
<xsl:copy-of select="../HEAD/*"/>
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1