Re: [xsl] XSL, when elements don't exist
Subject: Re: [xsl] XSL, when elements don't exist|
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Tue, 28 Oct 2003 15:24:55 -0500
At 02:37 PM 10/28/2003, you wrote:
I'm trying to process an XML document for which certain elements may or may
How can I handle this?
<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)
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
<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[@displayname='Defer Node Expansion']
or child::property[@displayname='Traverse DOM'])">
using the Boolean 'or' operator (and the not() function), or
<xsl:if test="not(child::property[@displayname='Defer Node Expansion'] |
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 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
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list