I want to transform the one XML message into other. My input message currently contains some empty elements with attributes @nil=ture value. What I want is that these elements should be created empty but without the nill attribute. Please see below my current progess:
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<collection>
<row>
<nr>A00</nr>
<type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
</row>
<row>
<nr>A01</nr>
<type>mash</type>
</row>
</collection>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="//*[local-name()='collection']">
<jsonArray>
<xsl:text disable-output-escaping="yes"><?xml-multiple?></xsl:text>
<xsl:for-each select="//*[local-name()='row']">
<jsonObject>
<xsl:copy-of select="node() except @nil" />
</jsonObject>
</xsl:for-each>
</jsonArray>
</xsl:template>
</xsl:stylesheet>
Current Output:
<?xml version="1.0" encoding="UTF-8"?>
<jsonArray>
<?xml-multiple?>
<jsonObject>
<nr>A00</nr>
<type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
</jsonObject>
<jsonObject>
<nr>A01</nr>
<type>mash</type>
</jsonObject>
</jsonArray>
Expected Output:
<?xml version="1.0" encoding="UTF-8"?>
<jsonArray>
<?xml-multiple?>
<jsonObject>
<nr>A00</nr>
<type/>
</jsonObject>
<jsonObject>
<nr>A01</nr>
<type>mash</type>
</jsonObject>
</jsonArray>
When you do <xsl:copy-of select="node() except @nil" />
you are copying the child elements of the current row
, which will copy them without changes. The except @nil
won't do what you expect because it will be looking for attributes called @nil
on the current row
element (and the attribute you are looking for is @xsi:nil
anyway.
Instead replace xsl:copy-of
with xsl:apply-templates
and add the identity template to your XSLT (with a slight tweak to remove namespace declarations).
<xsl:template match="@*|node()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
Then, you just need a template to ignore xsl:type
<xsl:template match="@xsi:nil" />
Try this XSLT
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="xsi">
<xsl:template match="@*|node()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="@xsi:nil" />
<xsl:template match="//*[local-name()='collection']">
<jsonArray>
<xsl:processing-instruction name="xml-multiple" />
<xsl:for-each select="//*[local-name()='row']">
<jsonObject>
<xsl:apply-templates select="@*|node()" />
</jsonObject>
</xsl:for-each>
</jsonArray>
</xsl:template>
</xsl:stylesheet>
(Do note you should really use xsl:processing-instruction
to create processing instructions).