Home > Software design >  How to change attribute values?
How to change attribute values?

Time:04-05

Input xml file:

<root>
  <x1 attr11="sd5">
    <x2 attr12="sd6" attr15="sd7">
      <a attr0="sd5"/>
      <b>
        <x3 attr18="sd8">
          <c>
            <x4 attr19="sd9" />
            <d awance="1" imlit="[0-200][201-300][301-1000]" />
            <e awance="2" imlit="[0-500][501-1900]" />
          </c>
        </x3>
      </b>
    </x2>
  </x1>
</root>

The "updates.xml" file from which updates are taken - the attributes of the a, b, c, d, e tags and the new "awance" and "imlit" tags, which are attributes in the input file:

<updates>
    <a attr1="adf" attr2="67" />
    <b attr3="g6h"/>    
    <c attr4="7jj" />   
    <d attr5="88" attr6="mn4" />    
    <e />
    <awance const="?" attr7="terd7"/>
    <imlit title="title" description="description">
        <Template>
          <Minimum title="min"  const="?" description="desc" />
          <Maximum title="max"  const="?" description="desc" />
        </Template>
    </imlit>
</updates>

If the input file contains a tag from the "updates.xml" file, then the attributes from the "updates.xml" file are copied into it. Also, if a tag in the input file has the "awance" and/or "imlit" attribute, then after transformation this attribute becomes a child tag instead of an attribute, and the value of the "awance" and/or "imlit" attribute from the input file becomes the value of the "const" attribute of the tags "awance" and/or "imlit" of the file after transformation, respectively. The file after XSLT1.0 transformation should look like this:

<root>
  <x1 attr11="sd5">
    <x2 attr12="sd6" attr15="sd7">
      <a attr0="sd5" attr1="adf" attr2="67" />
      <b attr3="g6h">
        <x3 attr18="sd8">
          <c attr4="7jj">
            <x4 attr19="sd9" />
            <d attr5="88" attr6="mn4">
              <awance const="1" attr7="terd7" />
              <imlit title="title" description="description">
                <Item key="1">
                  <Minimum title="min" const="0" description="desc" />
                  <Maximum title="max" const="200" description="desc" />
                </Item>
                <Item key="2">
                  <Minimum title="min" const="201" description="desc" />
                  <Maximum title="max" const="300" description="desc" />
                </Item>
                <Item key="3">
                  <Minimum title="min" const="301" description="desc" />
                  <Maximum title="max" const="1000" description="desc" />
                </Item>
              </imlit>
            </d>
            <e>
              <awance const="2" attr7="terd7" />
              <imlit title="title" description="description">
                <Item key="1">
                  <Minimum title="min" const="0" description="desc" />
                  <Maximum title="max" const="500" description="desc" />
                </Item>
                <Item key="2">
                  <Minimum title="min" const="501" description="desc" />
                  <Maximum title="max" const="1900" description="desc" />
                </Item>
              </imlit>
            </e>
          </c>
        </x3>
      </b>
    </x2>
  </x1>
</root>

Now this is the XSLT1.0 transformation file:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  exclude-result-prefixes="exslt"
  version="1.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space  elements="*"/>

  <xsl:param name="updates" select="document('updates.xml')"/>
  <xsl:key name="replacement" match="*" use="local-name()"/>

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

  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:variable name="this" select="."/>
      <xsl:for-each select="$updates">
        <xsl:apply-templates select="key('replacement', local-name($this))/@*"/>
        <xsl:choose>
          <xsl:when test="not($this[@awance])">
          </xsl:when>
          <xsl:otherwise>
            <xsl:variable name="const" select="$this/@awance"/>
            <xsl:variable name="replacement">
              <xsl:for-each select="$updates">
                <xsl:copy-of select="key('replacement', local-name($this))"/>
              </xsl:for-each>
            </xsl:variable>
            <xsl:variable name="awance" select="$updates//awance" />
            <xsl:copy-of select="$awance"/>
            <xsl:variable name="imlit" select="$updates//imlit" />
            <xsl:copy-of select="$imlit"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@awance" />
  <xsl:template match="@imlit" />

</xsl:stylesheet>

XML file after transformation:

<root>
  <x1 attr11="sd5">
    <x2 attr12="sd6" attr15="sd7">
      <a attr0="sd5" attr1="adf" attr2="67" />
      <b attr3="g6h">
        <x3 attr18="sd8">
          <c attr4="7jj">
            <x4 attr19="sd9" />
            <d attr5="88" attr6="mn4">
              <awance const="?" attr7="terd7" />
              <imlit title="title" description="description">
                <Template>
                  <Minimum title="min" const="?" description="desc" />
                  <Maximum title="max" const="?" description="desc" />
                </Template>
              </imlit>
            </d>
            <e>
              <awance const="?" attr7="terd7" />
              <imlit title="title" description="description">
                <Template>
                  <Minimum title="min" const="?" description="desc" />
                  <Maximum title="max" const="?" description="desc" />
                </Template>
              </imlit>
            </e>
          </c>
        </x3>
      </b>
    </x2>
  </x1>
</root>

How to change "const" attribute values?

CodePudding user response:

This should give you a good start.

<xsl:template match="@awance" />
<xsl:template match="@imlit" />

<xsl:template match="a|b|c|d|e">
  <xsl:variable name="name" select="local-name()"/>
  <xsl:copy>
    <xsl:apply-templates select="@*[local-name() != 'awance' and local-name() != 'imlit']"/>
    <xsl:apply-templates select="$updates//*[local-name() = $name]/@*"/>
    <xsl:apply-templates select="node()"/>
    <xsl:if test="boolean(@awance)">
      <xsl:element name="awance">
        <xsl:attribute name="const">
          <xsl:value-of select="@awance"/>
        </xsl:attribute>
      <xsl:apply-templates select="$updates//awance/@*[local-name() != 'const']"/>
      </xsl:element>
    </xsl:if>
    <xsl:if test="boolean(@imlit)">
      <xsl:element name="imlit">
        <xsl:apply-templates select="$updates//imlit/@*"/>
        <!-- I left this part for you.  Convert the delimited list in imlit from the 
             input file to a node-set and then for-each element.  Use the template  
             from the update file to output.  -->
      
  
      </xsl:element>
    </xsl:if>
  </xsl:copy>
</xsl:template>

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