tags:

views:

2486

answers:

3

I'm running through an XML document, selecting all the elements, and creating links based on the ancestor which is usually two nodes up in the tree, but occasionally 3 or 4 nodes up. For the majority of the elements, using <xsl:value-of select="translate(../../@name,$uc,$lc)" /> works just fine, but for the cases where the ancestor is 3 or so nodes up, I'd like to use <xsl:value-of select="translate(ancestor::package/@name,$uc,$lc)" />, but this doesn't work.

I'm using xsltproc from Ruby to do my XSL transforms.

Sample tree (yes, it has XSLT in it, no, I'm not trying to process it):

<package name="blork!" xmlns="http://xml.snapin.com/XBL"&gt;
  <xsl:template name="doSomething">
    <tokens>
      <token name="text-from-resource" export="public" />
    </tokens>
  </xsl:template>
</package>

The XSL I'm using:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s4="http://xml.snapin.com/XBL"&gt;
  <xsl:template match="/">
    <xsl:if test="count(//s4:token) >0">
      <xsl:text>Tokens!</xsl:text>
      <xsl:for-each select="//s4:token">
        <xsl:choose>
          <xsl:when test="@export='global'" />
          <xsl:otherwise>
            <xsl:value-of select="translate(ancestor::s4:package/@name,$uc,$lc)" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Edit: Ah, right, forgot the namespace on the select. The parser's finding that ancestor properly for most cases, but it still can't find it when there's an xsl: node in there, and the target file has no namespace for xsl. I'd prefer not to modify the target file, because it's production code---I'm just writing an autodoc tool.

+2  A: 

Your problem is probably namespace related. You haven't included those in the sample tree - can you be a bit more precise in what you've pasted? Assuming the package node is in the same namespace as the token node, try:

<xsl:value-of select="translate(ancestor::s4:package/@name,$uc,$lc)" />

You can also test just the unqualified name, though it will be slower:

<xsl:value-of select="translate(ancestor::*[local-name()='package']/@name,$uc,$lc)" />

W3C local-name() spec here.

Chris Marasti-Georg
A: 

I think there's no way around declaring the namespace for the 'xsl' prefix in the target doc as long as you're using namespace-aware XML processors. Are you not seeing any errors when you try to transform the target doc with xsltproc and the given stylesheet?

ChuckB
A: 

You might double-check what version of XSLT your tools are using. I believe XSLT 1.0 does not support "ancestor::<tag>..."

Eric Wendelin