xsl-list
[Top] [All Lists]

Re: XSL, when elements don't exist

2003-10-28 13:24:55
Tanya,

At 02:37 PM 10/28/2003, you wrote:
I'm trying to process an XML document for which certain elements may or may
not exist.
How can I handle this?
E.g.
<xsl:if test= "element exists"></xsl:if>
<xsl:if test= "element does not exist"></xsl:if>
...

The trick to this is knowing some of the details of how XPath works.

XPath has four data types. (XSLT 1.0 adds a fifth, the result-tree-fragment, which needn't concern us here.) They are:

node sets (sets of nodes in a source document)
numbers
strings
Booleans

In addition, XPath has rules about how to convert from any of these to the others. One of these rules, for converting a node set into a Boolean, is particularly handy: if the node set contains any nodes, it's true; if it doesn't, it's false.

Since a test attribute in a conditional expects a Boolean true or false, the trick for seeing whether a node exists is simply to retrieve it. If the set of nodes you get back contains any members, it passes the truth test; if it doesn't, it fails.

As I understand it, you need to do something special when nodes like these don't exist:

<property name="d" displayname="Defer Node Expansion" value="true" />
<property name="tr" displayname="Traverse DOM" value="true" />

...this would be (assuming your context node is the PropertyGroup):

<xsl:if test="not(child::property[(_at_)displayname='Defer Node Expansion']
               or child::property[(_at_)displayname='Traverse DOM'])">

using the Boolean 'or' operator (and the not() function), or

<xsl:if test="not(child::property[(_at_)displayname='Defer Node Expansion'] |
                  child::property[(_at_)displayname='Traverse DOM'])">

using the union operator '|', which combines two node sets.

If you apply the rule for converting node sets to Booleans in each case, you can see why they do the same thing here -- even though the 'or' operator is *not* the same as the '|' operator.

Incidentally, the casting rules referred to above make it generally superfluous in XSLT to write tests such as test="string-length(normalize-space($node) = 0", since you can always do things like test="not(normalize-space($node))" and get the same answer.

I hope this helps,
Wendell



======================================================================
Wendell Piez                            
mailto:wapiez(_at_)mulberrytech(_dot_)com
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
======================================================================


XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list



<Prev in Thread] Current Thread [Next in Thread>