Reputation:
i want to transform an XML File as following:
This is my main original XML file:
<persons>
<child name="child1"></child>
<adult name="adult1"></adult>
<child name="child2"></child>
<child name="child3"></child>
<COMMAND type="INSERT" file="otherchilds.xml"/>
<adult name="adult2"></adult>
<adult name="adult3"></adult>
</persons>
and there could be XML Files which should be imported by the XSLT whenever there is a tag COMMAND with an attribute "INSERT" in the main XML File. I have to use XSLT 1.0
otherchilds.xml:
<childs>
<child name="child4"></child>
<child name="child5"></child>
<childs>
the two XML Files should transform to one XML File:
<root>
<children>
<child1></child1>
<child2></child2>
<child3></child3>
<child4></child4>
<child5></child5>
</children>
<persons>
<child name="child1"></child>
<adult name="adult1"></adult>
<child name="child2"></child>
<child name="child3"></child>
<child name="child4"></child>
<child name="child5"></child>
<adult name="adult2"></adult>
<adult name="adult3"></adult>
</persons>
</root>
So whenever a child is found, it should be added in the children element.
Upvotes: 0
Views: 1720
Reputation: 167471
Using the XSLT code
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="persons">
<children>
<xsl:apply-templates select="child" mode="el"/>
</children>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="child" mode="el">
<xsl:element name="{@name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:transform>
the input
<persons>
<child name="child1"></child>
<adult name="adult1"></adult>
<child name="child2"></child>
<child name="child3"></child>
<adult name="adult2"></adult>
<adult name="adult3"></adult>
</persons>
is transformed to the result
<?xml version="1.0" encoding="utf-8"?>
<children>
<child1/>
<child2/>
<child3/>
</children>
<persons>
<child name="child1"/>
<adult name="adult1"/>
<child name="child2"/>
<child name="child3"/>
<adult name="adult2"/>
<adult name="adult3"/>
</persons>
Online sample at http://xsltransform.net/bnnZVR.
As for the changed requirements where there are additional elements to be loaded from a second file, the code can be changed to
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="persons">
<children>
<xsl:apply-templates select="child | document(COMMAND[@type = 'INSERT']/@file)//child" mode="el"/>
</children>
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="child" mode="el">
<xsl:element name="{@name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="COMMAND[@type = 'INSERT'][@file]">
<xsl:apply-templates select="document(@file)//child"/>
</xsl:template>
</xsl:transform>
to handle that particular case.
Upvotes: 1