Thomas Lann
Thomas Lann

Reputation: 1234

Using xslt to change an attribute value using arithmetic operations

I'm trying to bound the value of an xml attribute using xslt/xpath 1.0. In this example, it would be the id attribute on the m_m element.

<blart>
   <m_data>
      <m_m name="arggg" id="99999999" subs="asas"/>
   </m_data>
   <m_data>
      <m_m name="arggg" id="99" subs="asas"/>
   </m_data>
</blart>

If the id is greater then 20000 it gets set to 20000. I have the following xslt. I know it selects the correct node and attribute. It obviously is just outputing 20000. I realize I should have some sort of xpath logic in there but I'm having a hard time developing it. I have some big holes in my knowledge of xpath and xslt. If you can point me in the right direction in helping me understand on what I should be doing I would really appreciate it.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match ="m_data/m_m/@id[.&gt; 20000]">20000 </xsl:template>
</xsl:stylesheet> 

The expected output would be

<blart>
   <m_data>
      <m_m name="arggg" id="20000" subs="asas"/>
   </m_data>
   <m_data>
      <m_m name="arggg" id="99" subs="asas"/>
   </m_data>
</blart>

Upvotes: 0

Views: 752

Answers (3)

xbug
xbug

Reputation: 1472

NOTE: Since I posted this, much better answers were contributed (see here and here). SO won't let me delete this one because it was accepted, but in all fairness and for the sake of quality, I should encourage you to upvote the two aforementioned answers, so that they stand out over this one.


How about this:

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

<xsl:template match="m_m">
 <m_m>
  <xsl:copy-of select="@*" />
  <xsl:if test="@id &gt; 20000">
   <xsl:attribute name="id">20000</xsl:attribute>
  </xsl:if>
 </m_m>
</xsl:template>

<xsl:template match="m_data">
 <m_data>
  <xsl:apply-templates select="m_m" />
 </m_data>
</xsl:template>

<xsl:template match="/blart">
 <blart>
  <xsl:apply-templates select="m_data" />
 </blart>
</xsl:template>

</xsl:stylesheet>

Upvotes: 1

michael.hor257k
michael.hor257k

Reputation: 117018

Why don't you try:

XSLT 1.0

<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 ="m_m/@id[. > 20000]">
    <xsl:attribute name="id">20000</xsl:attribute>
</xsl:template>

</xsl:stylesheet>

Upvotes: 2

Linga Murthy C S
Linga Murthy C S

Reputation: 5432

You can use the following XSLT that gives flexibility to the attribute you want to change, and keeps everything else as it is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match ="m_data/m_m/@id[. &gt; 20000]">
    <xsl:attribute name="id">20000</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions