Re: [xsl] A few questions to the experts: functions, templates, loops

Subject: Re: [xsl] A few questions to the experts: functions, templates, loops
From: juggy@xxxxxxx
Date: Thu, 05 Sep 2002 17:32:58 +0200
Hi,

Michael Kay wrote:
... there are some things that I would really like to improve in my script:


1.) How do I write my own functions with return values? For example, I
have a function that traverses the tree, searches a page by id and
delivers the corresponding path-name. My solution up until now has been
to create a template (please, don't laugh at me - I know this is most
probably the worst possible approach) which delivers the name as text.
This works, but... it's sort of.. akward


Until you have xsl:function in XSLT 2.0, this is the best you can do.
Write a named template and return the result as a result-tree-fragment:

<xsl:variable..
  <xsl:call-template name=...
    <xsl:with-param..
  </
</

That's how I did it. I just thought this was not really the elegant way to do it :/


2.) I would like to have several templates matching e.g. "/test", but
for different purposes. Since I have some apply-templates they tell me
it's ambigous (which it of course is). Is there a way to elegantly
parameterize this?


Yes, this is what modes are for. Put a mode attribute on the
<xsl:template> rule and the same mode attribute on the
<xsl:apply-templates/> call.


3.) Is there a way to pass parameters when calling a xml-file? Like
calling "http://...file.xml?param=1"; and the xslt-script can evaluate
that parameter? I only found a way to do it via an xslt-processor, and
since I can't use scripts/cgis/processors... on my server it has to be
done via the xml/xslt purely.


Are you doing transformation on the client or on the server? It sounds
from this description as if you are doing it on the client. In this case
you can control the transformation, including passing parameters to it,
from Javascript code on the HTML page.

I am doing the basic transformation on the server. However, since this is just a private project and I don't have access to a server which gives me access to a full-fledged xslt-processor, I have to consider using a client-side transformation model as well.
You mentioned using javascript for that - how do I do that? Is there a short example on the web somewhere?
I would also líke to know if there is a way not to transfer the whole xml database before the browser applies the stylesheet selection to it. Example: I have a huge Kanji (Jap. character)/vocabulary database and parameterize it e.g. via javascript. Now I don't want the whole database to be transferred each time the user selects e.g. a Kanji., but only a distinctly accessible node by the stylesheet (like the entry number 1423). Is there a way to do that, or is using an xslt-processor the only option?

4.) Sometimes I couldn't use templates, e.g. because of ambigouty. Then
I usually used the xsl:for-each statement to select the corresponding
node (e.g. select="/pages/page"). But I don't need the
loop-functionality - is there a simpler statement to do so?


(a) See (2) above. (b) It depends what you want to do with the node.
Sometimes selecting it in <xsl:value-of> is all that you need, e.g.
<xsl:value-of select="ancestor::chap/@title"/>.

Thanks.

5.) Is there a way to "break out" of a loop?


No. <xsl:for-each> is not technically a loop - it is allowed to process
the nodes in any order, or in parallel, so long as the results are
assembled in the correct order. Because the execution isn't necessarily
sequential, breaking out would have undefined results.

I see. I didn't know about the non-defined order yet, but luckily I didn't rely on it (I made some pretty huge and complicated constructs which may be overblown, but my processor is fast and doesn't need to be done more than once ;-))

6.) How do I enter new data in an existing xml-file using saxon? I
didn't find any short, easy examples on that. Can anyone point me to a
source, please?


The usual technique is to write an identity template rule:


<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

Uh, I'll try that, though I wonder if saxon automatically changes the sourcefile or if I have to somehow overwrite it... But I'll see :)
and then to add further, more specific rules for elements that you don't
want to copy exactly. For example, if you want to add the attribute
@foo="bar" to the <empl> element with @id="12345", add the rule:

<xsl:template match="empl[@id='12345']">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:attribute name="foo">bar</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

Another question that arises: Is there a way to include a code-snippet (e.g. xsl-template) in my xsl-stylesheet not at the toplevel? e.g., if I have a xsl:when...< p1>...otherwise...< p2>...some common code...xsl:when... </ p1>...otherwise... </ p2>... I cannot do this producing (x)html as output because (naturally) it demands a closed < p?>. Now unless I wish to write "some common code" twice/thrice/... I have to put it in a variable, or is there a more elegant way?

Best regards,

Juggy

Always having difficulties switching between functional/non-functional/grammar-based language-approaches... ;-)

Michael Kay
Software AG
home: Michael.H.Kay@xxxxxxxxxxxx
work: Michael.Kay@xxxxxxxxxxxxxx



XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list





XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list


Current Thread