Creating new attribute based on another attribute value in XML using XSLT

Here should go questions about transforming XML with XSLT and FOP.
user05
Posts: 1
Joined: Mon Apr 04, 2022 10:29 am

Creating new attribute based on another attribute value in XML using XSLT

Post by user05 »

I need this input xml file :

Code: Select all

<response>
    <ActionValue>
      <entryMap name="entryvalue1">
        <action>
          <attribute name="type" value="apps jump" />
        </action>
      </entryMap>
      <entryMap name="entryvalue2">
        <action>
          <attribute name="type" value="phases2" />
        </action>
      </entryMap>
      <entryMap name="entryvalue3">
        <action>
          <attribute name="type" value="phases3" />
        </action>
      </entryMap>
      <entryMap name="...">
        <action>
          <attribute name="type" value="..." />
        </action>
      </entryMap>
    </ActionValue>
</response>
(The ... are for generalizing the input xml so that more phases and apps sections can be added.)

to be transformed to this output xml file :

Code: Select all

<response>
    <ActionValue>
      <entryMap name="entryvalue1">
        <action>
          <attribute name="type" value="apps jump" />
		  <attribute name="app_name" value="entryvalue1" />
        </action>
      </entryMap>
      <entryMap name="entryvalue2">
        <action>
          <attribute name="type" value="phases2" />
		  <attribute name="phase_name" value="entryvalue2" />
        </action>
      </entryMap>
      <entryMap name="entryvalue3">
        <action>
          <attribute name="type" value="phases3" />
		  <attribute name="phase_name" value="entryvalue3" />
        </action>
      </entryMap>
      <entryMap name="...">
        <action>
          <attribute name="type" value="..." />
          <attribute name="..." value="..." />
        </action>
      </entryMap>
    </ActionValue>
</response>
So, in the input file when I have <attribute name="type" value="apps jump" /> I need to add <attribute name="app_name" value="entryvalue1" /> right after <attribute name="type" value="apps jump" />. And when I have <attribute name="type" value="phases2" /> or <attribute name="type" value="phases3" /> or ANY VALUE in value="" in <attribute name="type"> other than "apps jump" then I need to add <attribute name="phase_name" value="entryvalue2" /> right after the attribute with type element i.e. for the 2nd case <attribute name="type" value="phases2" />.
Also, the value in <attribute name="app_name" value="entryvalue1" /> and <attribute name="phase_name" value="entryvalue2" /> and so on, holds the value of their corresponding entryMap name value.

Here for this example I have 1 app and 2 phase sections with app defined first and then the 2 phases are defined but that is not fixed. I can have multiple app and phase sections in any position in my input xml but on the same level. So I'm trying to create a generalized XSLT which will work on any number of app and phase sections.

The current sample XSLT I have right now is this :

Code: Select all

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

  <!-- Identity transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="action">
    <xsl:copy>
        <xsl:copy-of select="*"/>
        <attribute name="phase_name" value="{../@name}"/>
        <attribute name="app_name" value="{../@name}"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="action">
        <xsl:for-each select="attribute">
            <xsl:if test="@name='phase_name'">
            <xsl:value-of select="@value"/>
            </xsl:if>
            <xsl:if test="@name='app_name'">
            <xsl:value-of select="@value"/>
            </xsl:if>
        </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
 
If someone could please help me out with this, I'd be very grateful.
Last edited by user05 on Tue Apr 05, 2022 6:59 pm, edited 1 time in total.
Radu
Posts: 9424
Joined: Fri Jul 09, 2004 5:18 pm

Re: Creating new attribute based on another attribute value in XML using XSLT

Post by Radu »

Hi,

Maybe something like this would work:

Code: Select all

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs"
  version="2.0">
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="attribute[@name='type']">
    <!-- Copy current element as it is -->
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
    <xsl:choose>
      <xsl:when test="@value='apps jump'">
        <attribute name="app_name" value="{ancestor::entryMap/@name}" /> 
      </xsl:when>
      <xsl:otherwise>
        <attribute name="phase_name" value="{ancestor::entryMap/@name}" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Post Reply