XSL newbie here - please help!

G

gwoodhouse

Hello everyone,

Im brand new to XSL, im a java programmer by trade.

Problem:
What i need to do is put a variable in a for loop and extract an array
or set of variables from it.

Example:
I have a variable coming to the xsl in the format "hum|bla|lit"

I need to print this out as "Humanities, Black Studies, Literature"
but i dont know how to recursivly get what i need.

Current Code:
So far i can get the first part of the variable understood and
translated.

<xsl:param name="subject"><xsl:value-of select="substring-
before(.,'|')"/></xsl:param>
<xsl:choose>
<xsl:when test="$subject = 'wom'">
<subfield code="a">Women's Studies</subfield>
</xsl:when>
etc etc etc

Is there a function to split a variable so i can use a <xsl:for-each
select="splittingfunction(.,"|")"> type line?

Hope someone can help!

Graeme
 
G

gwoodhouse

update of the code:

<xsl:param name="subject"></xsl:param>
<xsl:for-each select="tokenize(.,'|')">
<xsl:choose>
<xsl:when test="$subject = 'wom'">
<xsl:param name="subject"><xsl:value-of
select="$subject"/> | Women's Studies</xsl:param>
</xsl:when>
</xsl:choose>
</xsl:for-each>
<subfield code="a"><xsl:value-of select="$subject"/></
subfield>

This doesnt work but hopefully you'll understand what i mean.

Thanks again for anyone who will help!

Graeme
 
M

Martin Honnen

Hello everyone,

Im brand new to XSL, im a java programmer by trade.

Problem:
What i need to do is put a variable in a for loop and extract an array
or set of variables from it.

Example:
I have a variable coming to the xsl in the format "hum|bla|lit"

I need to print this out as "Humanities, Black Studies, Literature"
but i dont know how to recursivly get what i need.

Current Code:
So far i can get the first part of the variable understood and
translated.

<xsl:param name="subject"><xsl:value-of select="substring-
before(.,'|')"/></xsl:param>
<xsl:choose>
<xsl:when test="$subject = 'wom'">
<subfield code="a">Women's Studies</subfield>
</xsl:when>
etc etc etc

Is there a function to split a variable so i can use a <xsl:for-each
select="splittingfunction(.,"|")"> type line?

Here is an XSLT 2.0 stylesheet that can be run with Saxon from
<http://saxon.sourceforge.net/>:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:mp="http://example.com/data"
version="2.0">

<xsl:param name="topics" select="'hum|bla|lit'"/>

<map xmlns="http://example.com/data">
<item key="hum" value="Humanity"/>
<item key="bla" value="Black Studies"/>
<item key="lit" value="Literature"/>
</map>

<xsl:template name="main">
<xsl:value-of select="for $t in tokenize($topics, '\|') return
document('')/*/mp:map/mp:item[@key = $t]/@value"
separator=", "/>
</xsl:template>

</xsl:stylesheet>
 
P

Pavel Lepin

What i need to do is put a variable in a for loop and
extract an array or set of variables from it.

There are no 'for loops' in XSLT. xsl:for-each is not a
loop, it's inline template application to a nodeset.

To emulate stateful loops in XSLT you would usually employ
recursive templates, using Divide & Conquer or tail
recursion approaches where possible.
I have a variable coming to the xsl in the format
"hum|bla|lit"

I need to print this out as "Humanities, Black Studies,
Literature" but i dont know how to recursivly get what i
need.

A crude implementation would be:

<c:cats xmlns:c="http://example.org/categories/">
<c:cat cat="bla">
<subfield code="a">Black Studies</subfield>
</c:cat>
<c:cat cat="hum">
<subfield code="b">Humanities</subfield>
</c:cat>
<c:cat cat="lit">
<subfield code="c">Literature</subfield>
</c:cat>
<c:cat cat="wom">
<subfield code="d">Women's Studies</subfield>
</c:cat>
</c:cats>
<xsl:template name="cats"
xmlns:c="http://example.org/categories/">
<xsl:param name="cats"/>
<xsl:variable name="car"
select="substring-before($cats,'|')"/>
<xsl:variable name="cdr"
select="substring-after($cats,'|')"/>
<xsl:apply-templates
select=
"
document('')/
*/c:cats/c:cat[@cat=$car or @cat=$cats]/node()
"/>
<xsl:if test="$cdr">
<xsl:call-template name="cats">
<xsl:with-param name="cats" select="$cdr"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

Don't use in production environments, it will choke on long
category lists.
Is there a function to split a variable so i can use a
<xsl:for-each select="splittingfunction(.,"|")"> type
line?

In XSLT1, xsl:for-each can only be invoked on nodesets.
XSLT2+XPath2 are a whole different story, but since you
failed to mention the processor you're using, I will not
elaborate any further.
 
G

gwoodhouse

Hi, thanks for your response =)

I was wondering if you could explain these lines to me:
<map xmlns="http://example.com/data"> (I tried google xsl, xml &
map and all i get is references to cocoon 1 and cocoon2)
<xsl:value-of select="for $t in tokenize($topics, '\|') return
document('')/*/mp:map/mp:item[@key = $t]/@value" separator=", "/>

What should the xmlns="" line read instead of example.com
How does the second line here know which "map" to use (for example).

Thanks again for your help martin, i can probably integrate this
without any real understanding but, i would prefer to not have to
bother you guys again :)

Again i appologise if all this that im asking is ridiculously simple
and im being dense.

Graeme
 
G

gwoodhouse

Thanks Pavel,

I understood even less of your post than the last reply =)

Do you have any advice for what subjects i should be researching in
order to understand lines like
*/c:cats/c:cat[@cat=$car or @cat=$cats]/node()

Which to me looks scarily complicated.

Also Pavel, nice quote :)

Graeme
 
M

Martin Honnen

I was wondering if you could explain these lines to me:
<map xmlns="http://example.com/data"> (I tried google xsl, xml &
map and all i get is references to cocoon 1 and cocoon2)

An XSLT stylesheet allows top-level elements that are not in the XSLT
namespace, for instance to store some data. My suggestion makes use of
that as that way you can easily "map" the short topic descriptions (e.g.
hum or lit) to the complete descriptions (e.g Humanity or Literature).
So the choosen elements names are arbitrary, you can choose any element
name you want, I chose "map" and "item".
The stylesheet can then access that data using
document('')/*/mp:map/mp:item as it does below:
<xsl:value-of select="for $t in tokenize($topics, '\|') return
document('')/*/mp:map/mp:item[@key = $t]/@value" separator=", "/>

What should the xmlns="" line read instead of example.com

You can choose any namespace URI you want or are allowed to use, you
just need to put those elements in a different namespace than the XSLT
namespace.
How does the second line here know which "map" to use (for example).

document('') refers to the stylesheet document itself, document('')/* is
the root element of the stylesheet, document('')/*/mp:map selects the
map element(s) in the namespace mp is bound to (e.g.
http://example.com/data).


See <URL:http://www.w3.org/TR/xslt20/#user-defined-top-level>
 
P

Pavel Lepin

Do you have any advice for what subjects i should be
researching in order to understand lines like
*/c:cats/c:cat[@cat=$car or @cat=$cats]/node()

It's an XPath1 expression (part of it, to be precise). Good
working knowledge of XPath is required for efficient
development of XSLT transformations. This is even more true
in case of XSLT2+XPath2.

Unfortunately, I'm unaware of any good, comprehensive
introductory materials on the subject of XSLT and XPath.
The resources I normally recommend to neophytes are XSLT
FAQ, IBM's developerWorks section on XML and XSLT, Mozilla
Developer Center's XSLT and XPath references, and W3C's
corresponding recommendations, but none of those are
precisely beginner-level.

The best way to learn XSLT right now seems to be solving
problems. Taking courses might work as well, but get expert
opinion beforehand - a poorly designed course is likely to
do more harm than good.

Basically, it'll take a good bit of effort on your part to
acquire firm understanding of XSLT basics, not in the least
because XSLT is quite different from bread-and-butter
general-purpose imperative languages. Familiarity with SQL
helps a little. So does familiarity with
Haskell/Scheme/Lisp/your-functional-language-of-choice or
Prolog (in fact, this helps much more that familiarity with
SQL).

Note that both of solutions posted, Martin's and mine, use
the same approach to generate the resulting tree. XSLT
processors ignore children of xsl:stylesheet element in the
namespaces they don't recognise (map element in Martin's
stylesheet and c:cats element in my snippet). Furthermore,
transformations can select nodesets from themselves, using
the document('') function. This is to avoid writing an
xsl:choose or anything along these lines.
 
D

David Carlisle

Hello everyone,

Im brand new to XSL, im a java programmer by trade.

Problem:
What i need to do is put a variable in a for loop and extract an array
or set of variables from it.

Example:
I have a variable coming to the xsl in the format "hum|bla|lit"

I need to print this out as "Humanities, Black Studies, Literature"
but i dont know how to recursivly get what i need.

Current Code:
So far i can get the first part of the variable understood and
tr

in xslt2 you'd do

<xsl:variable name="names">
<subject id="hum">Humanities</subject>
<subject id="bla">Black Studies</subject>
<subject id="lit">Literature</subject>
</xsl:variable>

<xsl:key name="names" match="subject" use="@id"/>

<xsl:template match="zzz">
<xsl:value-of
select="tokenize(.,'|')/key('names',.,$names)"
separator=", ">
</xsl:template>

In XSLT1 you'd write a recursive template splitting off one subject at a
time using substring-before.

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top