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
======================================================================