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[@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[@id = $id]">
...do your stuff with a matching $id=@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>