xsl-list
[Top] [All Lists]

Re: [xsl] Variable in XPath

2007-06-27 08:42:21
Hi Garvin,

see my comments:


Garvin Riensche wrote:
Hello,

I hope that anyone can help me with the following. I want to write a stylesheet that is used to check if an element (class) with a special ID which is given as variable from the commandline exists in the source or not. If no variable is supplied I want to test if there are "class" nodes at all. Of course it's no problem to check if a node with a special ID exists or not. But what do I use as default value of the variable so that all "class" nodes are selected if no variable is supplied.

?

<xsl:variable name="id" select="attribute::*"/>

Why a variable? You wanted to set it externally, in which case you better use a parameter.

Seems that you want the variable to hold the value of the current attribute by default? This only works when there's a context item, and there is no context item on the root level of a stylesheet, so this effectively means that your variable contains the empty sequence.

You could provide an absolute xpath, but then you would loose the context. I suppose this is cleaner instead and gives you all you need:

<xsl:param name="id" />


<xsl:template match="//condition/and-condition">

It is best practice (most of the time) *not* to use // in a match clause, it serves no purpose.


<xsl:when test="doc('factbase.xml')/facts/class[(_at_)id eq $id]">

The test should be true if $id is set to "2" or "3"

$id = (2, 3)

and if $id is not set at all.

assuming 'and' is semantically 'or' here (because $id = (2, 3) and empty($id) is never true):

$id = (2,3) or empty($id)

So, the key is the comparison "@id eq $id" and the default value of $id.

ah, you meant something else?....

"attribute::*" as default value is obviously wrong.

see above, it will give an empty sequence

Which default value do I have to use to test if class nodes exist at all?

I don't see why you want a default value for this, just don't use the $id:

empty(facts/class)

or, if you do some xsl:apply-templates, you probably don't have to worry about non-existing nodes at all (over-use of xsl:choose/when/if is a common cause of unstructured hard-to-maintain code):

<xsl:apply-templates select="facts/class" />

will not select 'class' when there is none.


Now that we put it all together, I assume you mean something like: if $id matches one or more @id, do something, if it matches none, but there are class-nodes, do something else, if there are no class-nodes, do something else. Here's one way to do it (in this case without xsl:choose, but you can of course use that if you feel more comfortable about it):

<xsl:param name="id" />

<xsl:template match="your-start">
   <xsl:apply-templates match="doc('factbase.xml')/facts/class" />
</xsl:template>

<xsl:template match="class[(_at_)id = $id]">
   ...do your stuff with a matching $id=(_at_)id for class-nodes...
</xsl:template>

<xsl:template match="facts[not(class/@id = $id)]/class">
...do your stuff when no @id matches the supplied $id, but class-nodes exist...
</xsl:template>

<xsl:template match="facts[empty(class)]">
  ...do your stuff when there are no class-nodes...
</xsl:template>


Happy coding!

Cheers,
-- Abel Braaksma



PS: alternatively, you could remove the second xsl:template match rule with the following, which reads easier and works equally well, because of priority rules:

<xsl:template match="class">
...do your stuff when no @id matches the supplied $id, but class-nodes exist...
</xsl:template>

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

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