RE: [xsl] Checking element to see if it has children...

Subject: RE: [xsl] Checking element to see if it has children...
From: "Lars Huttar" <lars_huttar@xxxxxxx>
Date: Tue, 9 Dec 2003 09:00:09 -0600
Hello JCS,

> Sent: Tuesday, December 09, 2003 7:33 AM
> Hi Jarno,
> Thanks for the response. I did check the FAQ again under
> "Empty Elements" to
> see about element checking. I think I ran into one those XSL "snafus"
> because when I ran a test to see if elements didn't have
> children, I didn't
> get any output when selecting ancestor::* (just the tests for
> "yes" came
> through). My head is still having a little trouble with this...

That seems obvious to me... how can an ancestor be childless?
(Well, the parent of a namespace node or an attribute node
could be childless, but the ancestor of an element node can't.)

Maybe I didn't understand your comment.
By "empty" / "didn't have children" do you mean
"don't have text node children"?
In that case your test should be
           <xsl:when test="not(text())">
instead of
           <xsl:when test="not(node())">

> But using the following stylesheet & data:
> -------------------
> <xsl:template match="/">
>     <xsl:for-each select="/*//*">
>         <xsl:call-template name="path"/>
>     </xsl:for-each>
> </xsl:template>
> <xsl:template name="path">
> <!--this is selecting the ancestors of current node-->
> <xsl:for-each select="ancestor::*">
>     <xsl:choose>
>           <xsl:when test="not(node())">
>         Not node: <xsl:value-of select="name()"/> has no children:
>           </xsl:when>
>           <xsl:when test="node()">
>             <font color="blue">
>                 <xsl:value-of select="name()"/>
>         </font>
>           </xsl:when>
>     </xsl:choose>
>     <xsl:text>/</xsl:text>
> </xsl:for-each>
>     <font color="red">
>         <xsl:value-of select="name()"/>
>     </font>
> <br/>
> </xsl:template>
> </xsl:stylesheet>
> ----------
> <root>
> <element_one>one</element_one>
> <element_two>two</element_two>
> <element_three>thing</element_three>
> <element_four>
>     <element_four_one>
>     </element_four_one>
> </element_four>
> </root>
> ------------
> I get the following:
> root /element_one
> root /element_two
> root /element_three
> root /element_four
> root /element_four /element_four_one
> But I would like the output to be:
> root /element_one
> root /element_two
> root /element_three
> root /element_four /element_four_one
> Because ³element_four² is a container and has no text, it
> shouldn¹t be a red
> ³stub².

It sounds like you don't want the "path" template to be
called for <element_four>.
Did you try David Carlisle's suggestion? I.e. change
   <xsl:for-each select="/*//*">
   <xsl:for-each select="//*[not(*)]">

or, since your criterion is "is a container and has no text",
   <xsl:for-each select="//*[not(*) or text()]">

That should do what you want.

Incidentally, I agree that the XSL FAQ can be hard to
find answers in, and the answers there are difficult to
understand. What we need is for someone who has time, to
write up an FAQ that focuses on answering questions, rather than
a collection of scattered excerpts from discussions.
And someone needs to develop a good index for it.
Not a trivial task.

However, the collection there is better than nothing, and
I appreciate Dave's time in putting it together.
I've found some good answers there.

(And by the way, unfortunately we can't assume that just because
someone posts to this list they have searched the FAQ.
Unless they say so.)

 XSL-List info and archive:

Current Thread