Re: [xsl] recursively descending through a node set to maintain white space integrity help!

Subject: Re: [xsl] recursively descending through a node set to maintain white space integrity help!
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Fri, 7 Sep 2001 09:48:26 +0100
Hi Utah,

> I am usilizing XSLT to transform a framed site into a flat site.
> Currently im using XERCES-J/XALAN-J to develop the templates but I
> intend to use XT to perform the final transform...

If you're using XT, it's probably a good idea to develop with XT as
well. XT is not 100% XSLT compliant, so you might find that you
develop a template in Xalan and that it then doesn't work with XT.

> Therefore I have had to abandon the use of copy-of elements and
> recursively called copy elements.

When you're working over nodes, it's usually easiest to use matching
templates rather than named templates. You should probably start with
the identity template, which copies nodes recursively:

<xsl:template match="@*|node()">
    <xsl:apply-templates select="@*|node()" />

Then to copy the content of a particular document, you should apply
templates to its content:

  <xsl:apply-templates select="document($document)/*" />

You could make a template that copied the entirety of a document with:

<xsl:template name="copyDocument">
  <xsl:param name="whichDocument" select="$document" />
  <xsl:apply-templates select="document($whichDocument)/*" />

If you want to pass the name of an element into the template as well,
you can create a template that copies all the elements of that name in
that document by looking for a descendant element whose name() is the
same as the name you pass in:

<xsl:template name="copyDocument">
  <xsl:param name="whichDocument" select="$document" />
  <xsl:param name="whichElement" select="$element" />
    select="document($whichDocument)//*[name() = $whichElement]" />

To keep track of the location of the context node, so that you can add
an ID to it, you probably want an element-specific template, something

<xsl:template match="*">
  <xsl:param name="ID" />
  <xsl:element name="{name()}">
    <xsl:attribute name="id">
        select="concat($ID, '/', name(), '[', position(), ']')" />
    <xsl:apply-templates select="@*|node()" />

> My specific question regards XPATH!
> I have tried several iterations of...
> document($whichDocument)/$whichNode/*
> including but not limited to...
> document($whichDocument)/{$whichNode}/*;
> document($whichDocument)/'$whichNode'/*;

None of the above paths are legal. Variable references can only be
used at the beginning of paths or within predicates (or function calls
at the beginning of paths), not in the middle of paths.

> document($whichDocument)/[*=$whichNode]/*;
> document($whichDocument)/[.=$whichNode]/*;

These are closer (although still not legal). Given that $whichNode is
the name of an element, you want to select the descendant element in
the document that has that name, and do something with its children:

  document($whichDocument)//*[name() = $whichNode]/*

I assume you want descendant elements rather than only the document

> accessing the document works... (except the document seems to have
> to be in the same directory which irritates me... could be a XALAN-J
> problem?)

The document() function accesses documents relative to the stylesheet
if you use it with one argument. You can add a second argument to make
it access documents relative to the current XML document with:

  document($whichDocument, /)

The second argument is a node from a document whose base URI is used
to resolve the path given as the first argument.

> How do I select the value of the attribute currently being looped
> though? As I understand I am selecting the node one time for each
> attribute it contains... Can I reference the "context attribute" in
> such a way as that I could extract its value?

You can use . to access the context node, or current() to access the
current node (which is the same thing unless you're within a

I hope that helps,


Jeni Tennison

 XSL-List info and archive:

Current Thread