RE: [xsl] Implementing a (fairly) complex business rule

Subject: RE: [xsl] Implementing a (fairly) complex business rule
From: "Bradley, Peter" <pbradley@xxxxxxxxxx>
Date: Tue, 30 Sep 2008 16:12:21 +0100
Wendell,

That's very clear.  Thanks.  And your diagnosis is spot on, of course.

I remember you helping me out some years ago when I was "doing" xslt as
part of an MSc course.  This is my first look at xslt since then, so you
can imagine I've forgotten quite a lot.  It's coming back though -
although you may have to put up with me plaguing the list for a while!

(I got the MSc, BTW, with distinction)

:)


Peter


-----Original Message-----
From: Wendell Piez [mailto:wapiez@xxxxxxxxxxxxxxxx]
Sent: 30 September 2008 15:39
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Implementing a (fairly) complex business rule

Peter,

At 09:07 AM 9/30/2008, you wrote:
>       <xsl:if test="string-length(s0:POSTCODE/text() = 0)">
>         <xsl:attribute name="ReasonForNull">
>           <xsl:text>1</xsl:text>
>         </xsl:attribute>
>       </xsl:if>

This won't work as a test for whether s0:POSTCODE has a null value.
For one thing, "null value" is undefined in XSLT. Null values in your
XML in any number of ways.

More seriously, however, you have

string-length(s0:POSTCODE/text() = 0)

This measures the length of the string returned by casting the
expression "sO:POSTCODE/text()=0". This is a numeric comparison,
returning true if you have <s0:POSTCODE>0</s0:POSTCODE> (or some
other lexical representation of 0, such as "0.0"), and false
otherwise. Cast to a string, this is either "true" or "false". (In
XPath 1.0. In XPath 2.0 you would get an error for trying to measure
the string length of a Boolean.) The string length of "false" is 5,
"true" is 4. Either 4 or 5 always tests true. So you will always get
your @ReasonForNull[.='1'].

So you are looking at one of those unhelpful occasions where XPath
silently errors on you, without telling you so, by faithfully
executing what you have asked for.

Now, I'm guessing you meant

string-length(s0:POSTCODE/text()) = 0

This looks like it should work: it measures the length of
s0:POSTCODE's text node, and returns true if it is 0.

However, I wouldn't recommend this either. It will test true when
s0:POSTCODE has no value at all, since in that case, it has no text
node, and the string length of a node that does not exist is zero.

But it's fairly brittle, since it will fail if your input, for example,
has

<s0:POSTCODE>  </s0:POSTCODE>

(i.e. whitespace-only content but not zero-length)

which comes back to my opening remark that the notion of "null value"
has to be defined before we can write the expression properly.

This is not an infrequent problem. Often a defensive coder will
define "null value" as "no value or whitespace-only value". In this
case, a good test is:

<xsl:if test="not(normalize-space(s0:POSTCODE))">
... </xsl:if>

The normalize-space() function collapses a whitespace-only value into
an empty string. The string value is cast to a Boolean for the not()
function, by the rule that empty strings are false and non-empty
strings are true. not(), of course, inverts this Boolean value, so we
get true when s0:POSTCODE has no value (except possibly for whitespace).

Saying s0:POSTCODE/text() isn't necessary, since the string value of
the element itself will do. Indeed, if any comments or processing
instructions are present, looking at the first text node (in XSLT
1.0) won't do: we want the value of s0:POSTCODE itself.

So the problems here reduce to (a) having the parethesis misplaced,
and then potentially (b) writing a test which doesn't necessarily
perform the test you actually want. We see expressions like (b) since
they are common in other languages. But in XSLT (or actually, here,
XPath), other idioms frequently turn out to be both cleaner and more
robust (while demanding a bit of an education to learn).

Then too, sometimes the definition of "null value" includes values
like "0" or "NULL". Which is a different story altogether.

Cheers,
Wendell



======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================

Current Thread