Re: [xsl] Using name() with XPath expressions (fwd)

Subject: Re: [xsl] Using name() with XPath expressions (fwd)
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Sat, 14 Jul 2001 08:58:42 +0100
Hi Jenny,

> The problem is that if the variable $field contains the path of a
> text node instead of the name itself, the name function doesn't
> work. For example, if $field contains 'author/lastname', the name
> function assumes that 'author/lastname' is the string value of the
> name of a node instead of the path to a node. How do I alter this
> comparison so that it works with $field values that are paths as
> well as field values that are names? Thanks in advance.

If there are only two levels of children under bibitem, then you could
use a more general solution that used the substring before the '/' to
find the name of the child, and the substring after the '/' to find
the name of the grandchild:

<xsl:for-each select="bibliography/bibitem">

  <xsl:if test="(contains($field, '/') and
                 $search = *[name() = substring-before($field, '/')]
                           /*[name() = substring-after($field, '/')]) or
                $search = *[name() = $field]">
    <xsl:call-template name="printBib" />
  </xsl:if>

</xsl:for-each>

You can continue doing this kind of thing to an arbitrary depth, but
if you get past grandchildren you may find it simpler to create a
template that retrieves the value of the relevant descendant when
passed a path as a parameter. This template works by stepping
recursively down the path:

<xsl:template match="*" mode="string-value">
  <xsl:param name="path" />
  <xsl:choose>
    <xsl:when test="contains($path, '/')">
      <xsl:apply-templates mode="string-value"
          select="*[name() = substring-before($path, '/')]">
        <xsl:with-param name="path"
                        select="substring-after($path, '/')" />
      </xsl:apply-templates>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="*[name() = $path]" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

You can call this template to find the value of the node indicated by
the path, which you then test against the search string:

<xsl:for-each select="bibliography/bibitem">

  <xsl:variable name="value">
    <xsl:apply-templates select="." mode="string-value">
      <xsl:with-param name="path" select="$field" />
    </xsl:apply-templates>
  </xsl:variable>

  <xsl:if test="$search = $value">
    <xsl:call-template name="printBib" />
  </xsl:if>

</xsl:for-each>

If you reach a point where the $field parameter contains arbitrary
XPaths, including predicates and axes other than the child axis, then
you need to start thinking about using extension functions like
saxon:evaluate() to evaluate the location path, or creating XSLT using
XSLT.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread