Home > Enterprise >  XSLT - Change child attribute if parent attribute contains specific text
XSLT - Change child attribute if parent attribute contains specific text

Time:12-29

I am very new to XSLT and no familiar at all with the logic behind. I have the following XML:

<config>
  <connection port="4404" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
      <selection name="test-mode" enabled="true"/>
  </connection>

  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownload>
  </option>
  
</config>

After applying some transformation from XLST - Copy XML tag and replace attribute value, I was able to copy the connection tags and change the port attribute based on the previous value.

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
</config>

Here is my XSLT:

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

    <!--  Initial template to copy all nodes and attributes  -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="connection[@port]">
        <xsl:copy>
            <!-- Copy all nodes and attributes -->
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="port">
                <xsl:value-of select="concat('78', substring(@port,3,2))"/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

   
</xsl:stylesheet>

Goal: In addition to change the port attribute, I'm trying to change the attribute enabled="false" to the newly copied elements (connection elements that has a port that contains '78')

XML output desired:

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
</config>

Is there a way to directly update the attribute during the copy or is it necessary to create a new template ?

CodePudding user response:

It could be done in one shot.

Input XML

<config>
    <connection port="4404" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>
    <connection port="4405" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>
    <connection port="4406" type="tcp">
        <selection name="test-mode" enabled="true"/>
    </connection>

    <option>
        <maxNumberOfDownloads>10</maxNumberOfDownloads>
    </option>
</config>

XSLT

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="connection[@port]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="port">
                <xsl:value-of select="concat('78', substring(@port,3,2))"/>
            </xsl:attribute>
            <!--<xsl:apply-templates/>-->
            <selection>
                <xsl:apply-templates select="selection/@*"/>
                <xsl:attribute name="enabled">
                    <xsl:value-of select="'false'"/>
                </xsl:attribute>
            </selection>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output

<config>
  <connection port="4404" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7804" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="4405" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7805" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <connection port="4406" type="tcp">
    <selection name="test-mode" enabled="true"/>
  </connection>
  <connection port="7806" type="tcp">
    <selection name="test-mode" enabled="false"/>
  </connection>
  <option>
    <maxNumberOfDownloads>10</maxNumberOfDownloads>
  </option>
</config>
  • Related