Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Add to an Element, Creating it First If Needed

Tags:

xslt

xslt-1.0

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.

like image 862
uncaged Avatar asked Dec 03 '25 09:12

uncaged


2 Answers

<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>
like image 124
Emiliano Poggi Avatar answered Dec 06 '25 05:12

Emiliano Poggi


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>
like image 24
Maestro13 Avatar answered Dec 06 '25 06:12

Maestro13



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!