XSL Noob
XSL Noob

Reputation: 51

XSL Ignoring Elements that are Blank or Equal to 0

I'm doing an XSLT Transformation and I want to ignore elements that have a value of zero as well as elements that are blank. A sample of the XML I am using is shown below

<row>
 <col1>a</col1>
 <col2></col2>
 <col3>0</col3>
</row>

For example, I have tried using:

<xsl:if test="col2 != '0' or col2 != ' '><xsl:value-of select="col2"/></xsl:if>

but it to filter out everything instead of just filtering the data that are blank or zero. But this doesn't work. What am I doing incorrectly?

Upvotes: 0

Views: 2240

Answers (3)

Saurav
Saurav

Reputation: 640

You can also try out this one

  <xsl:for-each select="row/*">
    <xsl:if test="normalize-space(.)!=''">
      <xsl:if test=".!='0'">
        <xsl:copy-of select="."/>
      </xsl:if>
    </xsl:if>               
  </xsl:for-each>

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 116982

Your test is a classic tautology: x!=a or x!=b is always true, because when x=a then the second proposition is true, when x=b then the first proposition is true, and when x=c, both are true. In terms of logic, you need to write x!=a AND x!=b.

In terms of XSLT, if col2 is supposed to be a non-zero numeric value, you could formulate your test as:

<xsl:if test="number(col2)">

I am not sure in what context you are testing this; usually it's best to eliminate the unwanted elements before having to deal with them, for example by:

<xsl:apply-templates select="col2[boolean(number(.))]"/> 

Upvotes: 1

Tim C
Tim C

Reputation: 70608

What you are doing incorrectly is that you are using an or instead of an and. Additionally, you are also checking for a single space, not an empty element. So, if you consider spaces as 'blanks' you should use the normalize-space function

<xsl:if test="col2 != '0' and normalize-space(col2) != ''">

Note, depending on what you are actually trying to achieve, it may probably be better to use template matching here, instead of xsl:if

Try this for example

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:template match="row">
        <xsl:copy>
            <xsl:apply-templates select="*[. != '0' and normalize-space(.) != '']" />
        </xsl:copy>
    </xsl:template>

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

Alternatively, you can use a 'pull' approach, and write template to ignore empty elements (as opposed to specifically selecting the ones you want to copy). This would also work

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

    <xsl:template match="row/*[. = '0' or normalize-space(.) = '']" />

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

Upvotes: 1

Related Questions