xmlxsltsaxonsaxon-js

How to dynamically add child elements to an existing element using XSLT 3.0?


I have an XML file containing a main element <root> with a child element <item>. I also have other elements elsewhere in the document that contain information I want to add as new child elements to the existing <item>. Thes elements that i want to transform should have a condition (code="code01"), for other codes the attributes should become new child tags with a prefix __.

here is a simple example of my xml file :


    <root>
      <item>
        <ref>Initial Value</ref>
      </item>
      <extraData>
        <constant code="code01">
          <value>New Value</value>
          <othertags>Random thing</othertags>
        </constant>
        <constant code="code02">
          <value>New Value 2</value>
          <othertags>Random thing 2</othertags>
        </constant>
      </extraData>
      
    </root>

i want to transform it so that it can look like the following :


    <root>
      <item>
        <ref>Initial Value</ref>
        <newTag>New Value</newTag>
      </item>
      <extraData>
        <constant>
          <__code> code02 </__code>
          <value>New Value 2</value>
          <othertags>Random thing 2</othertags>
        </constant>
      </extraData>
      
    </root>

How can i achieve this using an xslt transformation please i'm beginner to this ?


Solution

  • Well, one step at a time.

    To get from

    <item><ref>Initial Value</ref></item>
    

    to

    <item>
       <ref>Initial Value</ref>
       <newTag>New Value</newTag>
    </item>
    

    you need a template rule such as

    <xsl:template match="item">
       <xsl:copy>
           <xsl:copy-of select="*"/>
           <newItem>
               <xsl:value-of select="//extraData/constant[@code='code01']/value"/>
           </newItem>
       </xsl:copy>
    </xsl:template>
    

    To remove the code01 element, you need the template rule:

    <xsl:template match="constant[@code='code01']"/>
    

    To convert the other constant elements, you need a rule such as:

    <xsl:template match="constant[@code != 'code01']">
       <constant>
          <__code><xsl:value-of select="@code"/></__code>
          <xsl:copy-of select="*"/>
       </constant>
    </xsl:template>