Re: [xsl] would like to simplify my XSLT

Subject: Re: [xsl] would like to simplify my XSLT
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Tue, 30 Jan 2007 10:50:26 +0100
Glen Mazza wrote:
--- Abel Braaksma <abel.online@xxxxxxxxx> wrote:
Newbie question here--but why do you match on "* |
text()" instead of just matching on "/"? (I saw the
physical answer--by matching on the latter I got a lot
of strange white space--but I'm not sure why.)

Well, depending on your processor and the way it treats whitespace, you indeed see a bunch of whitespace nodes. But you should also see the names of 'Chris' and 'John' as text between the output nodes, because they fall into the default template. This means: any input that does not have a corresponding match, but does have an "apply-templates", will be stripped off of all nodes and only the text is output.


This is most visual when you make a stylesheet with nothing in it (only opening and closing tag xsl:stylesheet). This will output all bare text of your input, because the implicit call is apply-templates to your document root (i.e., as if you strip all tags and attributes+values).

If you were to just have the "/" match, you only match the root node, and not the text() nodes that you (may) want to get rid of. I call this kind of template a throw-away template. Adding "xsl:apply-templates" makes sure that any children are processed (if you remove it, you will not see any output).

However, if there is nothing more you want to do with the other children, you can replace it like this, which is simpler:

<xsl:template match="text" />

because the non-text nodes by themselves will not output anything with the aforementioned default template, only the text does.


<person name="Chris" />

That's correct, but this is not exactly what I needed. I wanted names of people who didn't have *any* documents in the document list--Chris shouldn't appear because he had one of his two documents there.

By removing the "not" in your XPATH above, that gave
me people who have at least one document in the
document list, useful but still not what I was looking
for.

I'll check the other responses to see if they will
help.

I beg to disagree. I quote from your original message:


"For example, Chris above has no
documents in the <documents> list (relid=4 and 7
aren't there), so he would get listed, but John above
wouldn't, because his "2" is in the list."

Which, imho, says "chris has [4, 7], documents has [1,2], so show chris". Which is illustrated by your own sentence "so he would get listed", where "he" presumably refers to "Chris" ;)

My solution does exactly the same as the other solutions (i.e., it shows "Chris"). And it closely resembles there XPaths too (see the last match clause and compare it).

To complete the story, here's a copy of the input (from your message) that I used:

     <data>
           <documents>
               <document id="1"/>
               <document id="2"/>
           </documents>
           <persons>
               <person>
                   <name>Chris</name>
                   <document relid="4"/>
                   <document relid="7"/>
               </person>
               <person>
                   <name>John</name>
                   <document relid="2"/>
               </person>
           </persons>
       </data>


I know -- I come from a Java background so that's how
my XSLT will currently look until I figure out how to
do things better!

The trick with XSLT is: let XSLT do the work for you. You define the rules, XSLT defines the execution path. This means: very few xsl:if and xsl:choose and for-each, if any (but sometimes you do need them).


Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

Current Thread