I need to add elements to an element, creating it first if it doesn't already exist.
My desired final result, after adding ABC and DEF, is:
<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Q/>
<B>
<string>ABC</string>
<string>DEF</string>
</B>
<A>
I thought that the following would accomplish this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Identity transform -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Insert a B element if it doesn't exist. -->
<xsl:template match="A[not(B)]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<B/>
</xsl:copy>
</xsl:template>
<xsl:template match="B">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<string>ABC</string>
<string>DEF</string>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If I start with the following, in which <B> already exists, it works fine, returning the result above:
<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
<Q/>
<B/>
</A>
However, if I don't have a <B>, as in below:
<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
<Q/>
</A>
then it creates the <B> as below, but doesn't insert ABC and DEF:
<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
<Q/>
<B/>
</A>
So, what am I missing? Thanks in advance.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Identity transform -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Insert a B element with string elements if it doesn't exist. -->
<xsl:template match="A[not(B)]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<B>
<xsl:call-template name="add-strings"/>
</B>
</xsl:copy>
</xsl:template>
<!-- Add string elements to existing B if missing -->
<xsl:template match="B[not(string)]">
<xsl:copy>
<xsl:call-template name="add-strings"/>
</xsl:copy>
</xsl:template>
<!-- Add string elements to caller -->
<xsl:template name="add-strings">
<string>ABC</string>
<string>DEF</string>
</xsl:template>
</xsl:stylesheet>
You will have to add the sub tags of B too when B does not exist, as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- Identity transform -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Insert a B element if it doesn't exist. -->
<xsl:template match="A[not(B)]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<B>
<string>ABC</string>
<string>DEF</string>
</B>
</xsl:copy>
</xsl:template>
<xsl:template match="B">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<string>ABC</string>
<string>DEF</string>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when applied to
<?xml version="1.0" encoding="UTF-8"?>
<root>
<A>
<Q/>
</A>
<A>
<Q/>
<B/>
</A>
</root>
this gives
<?xml version="1.0" encoding="UTF-8"?>
<root>
<A>
<Q/>
<B>
<string>ABC</string>
<string>DEF</string>
</B>
</A>
<A>
<Q/>
<B>
<string>ABC</string>
<string>DEF</string>
</B>
</A>
</root>
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