0

I need to transform following xml as Expected Output using xsl 3.0 or xsl 2.0. Need to add new element called <key> </key> for each <row> element by combining its legacyID and company.

Input XML:

<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC</legacyID>
         <AssociateID>123</AssociateID>
      </Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

Expected Output:

<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC<legacyID>
         <AssociateID>123<AssociateID>
      <Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <key>ABC_Test Company 2</key>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

I used following xsl code,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
   <xsl:template match="root/*">
      <xsl:copy>
         <xsl:element name="key">
            <xsl:value-of select="concat(//root/row/legacyID,' ',/row/company)" />
         </xsl:element>
         <xsl:call-template name="copy-children" />
      </xsl:copy>
   </xsl:template>
   <!-- Copy the children of the current node. -->
   <xsl:template name="copy-children">
      <xsl:copy-of select="./*" />
   </xsl:template>
   <!-- Generic identity template -->
   <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="@*" />
         <xsl:apply-templates />
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

But this gave the output like below,

<?xml version="1.0" encoding="UTF-8"?>
<AggregatedData>
   <Data>
      <Entry>
         <legacyID>ABC</legacyID>
         <AssociateID>123</AssociateID>
      </Entry>
      <Entry>
         <legacyID>CDE</legacyID>
         <AssociateID>456</AssociateID>
      </Entry>
   </Data>
   <root>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>ABC</legacyID>
         <company>Test Company 1</company>
         <firstname>Test1</firstname>
      </row>
      <row>
         <key>ABC_Test Company 1</key>
         <legacyID>CDE</legacyID>
         <company>Test Company 2</company>
         <firstname>Test2</firstname>
      </row>
   </root>
</AggregatedData>

According to above output both row values updated with the same key value. I need to correct that and need to use xsl 2.0.

3
  • 1
    This seems trivial. Where are you stuck? Commented May 18, 2022 at 18:39
  • @Sebastien I have updated the question with the code and more details. Commented May 18, 2022 at 19:11
  • Is the second key in your example correct? Commented May 19, 2022 at 19:43

2 Answers 2

1

In XSLT 3.0 you could reduce the code to:

<xsl:stylesheet version="3.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
expand-text="yes">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:mode on-no-match="shallow-copy"/>

<xsl:template match="row/legacyID">
    <key>{.}_{../company}</key>
    <xsl:copy-of select="."/>
</xsl:template>
  
</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

0

You could do it like this :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="row">
    <xsl:copy>
      <key>
        <xsl:value-of select="concat(legacyID,'_',company)"/>
      </key>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  
  <!-- Identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

See it working here : https://xsltfiddle.liberty-development.net/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.