[xsl] xpath confusion (compound xpath)

Subject: [xsl] xpath confusion (compound xpath)
From: S Woodside <sbwoodside@xxxxxxxxx>
Date: Sat, 18 Jan 2003 15:40:37 -0500
I have the following source XML. If you're familiar with relax NG you 'll see that it's an RNG grammar.

<grammar>
  <start>
    <element>
      [...]
      <zeroOrMore>
        <choice>
          <!-- interesting part (1) starts here -->
          <element name="objective">
            <optional>
              <attribute name="id">
                <data type="ID" />
              </attribute>
            </optional>
            <oneOrMore>
              <element name="para">
                <zeroOrMore>
                  <text />
                </zeroOrMore>
              </element>
            </oneOrMore>
          </element>
          <!-- interesting part ends here -->
        [...]
        </choice>
      [...]
    </element>
    [...]
  </start>
</grammar>

The Xpath to the subtree (1) that I'm interested in is
/grammar/start/element/zeroOrMore/choice/element[1] (call this (2))

What I wish to do is to apply templates to the subtree (1) where I will determine if there is a "zeroOrMore" node between the XPath (2) and the context node. However I'm having major trouble, I can't figure out how to make it work. Here's a simple test XSLT test.xsl that has the xpath (2) hardcoded into it for testing purposes.


<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> <xsl:output method="text"/> <xsl:strip-space elements="*"/>

<xsl:template match="/">
<xsl:apply-templates select="/grammar/start/element/zeroOrMore/choice/element[1]"/>
</xsl:template>


<xsl:template match="/grammar/start/element/zeroOrMore/choice/element[1]">
<xsl:call-template name="testit"/>
</xsl:template>
<xsl:template match="/grammar/start/element/zeroOrMore/choice/element[1]//*">
<xsl:call-template name="testit"/>
</xsl:template>


<xsl:template name="testit">
<xsl:choose>
<xsl:when
test="/grammar/start/element/zeroOrMore/choice/element[1]//zeroOrMore// *[self=current()]">
<xsl:call-template name="thepath"/>
<xsl:text> YES</xsl:text>
<xsl:text>&#xA;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="thepath"/>
<xsl:text> NO</xsl:text>
<xsl:text>&#xA;</xsl:text>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>


<!-- see "thepath" template at the end of the email, it's code from the list -->
</xsl:stylesheet>


Here's the output from sablotron:

[simons-tibook:~/Sites/AxkitSite] woodside% sabcmd test.xsl form.html
/grammar/start/element/zeroOrMore/choice/element[1] NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional/attribute NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional/attribute/ data NO
/grammar/start/element/zeroOrMore/choice/element[1]/oneOrMore NO
/grammar/start/element/zeroOrMore/choice/element[1]/oneOrMore/element NO
/grammar/start/element/zeroOrMore/choice/element[1]/oneOrMore/element/ zeroOrMore NO
/grammar/start/element/zeroOrMore/choice/element[1]/oneOrMore/element/ zeroOrMore/text NO


It's all right, except for the last one, which should be a YES.

Here's the even stranger output from xsltproc:

[simons-tibook:~/Sites/AxkitSite] woodside% xsltproc test.xsl form.html
/grammar/start/element/zeroOrMore/choice/element[1] NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional/attribute NO
/grammar/start/element/zeroOrMore/choice/element[1]/optional/attribute/ data NO
/grammar/start/element/zeroOrMore/choice/element[1]/oneOrMore/element NO


(Why did xsltproc stop there???)

What am I doing wrong?

Simon


------


The "testit" template

<xsl:template name="thepath">
<xsl:variable name="theResult">
<xsl:variable name="theNode" select="."/>
<xsl:for-each select="$theNode | $theNode/ancestor-or-self::node()[..]">
<xsl:element name="slash">/</xsl:element>
<xsl:choose>
<xsl:when test="self::*">
<xsl:element name="nodeName">
<xsl:value-of select="name()"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::*[name(current()) = name()])"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::*[name(current()) = name()])"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition + 1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:otherwise> <!-- This node is not an element -->
<xsl:choose>
<xsl:when test="count(. | ../@*) = count(../@*)">
<!-- Attribute -->
<xsl:element name="nodeName">
<xsl:value-of select="concat('@',name())"/>
</xsl:element>
</xsl:when>
<xsl:when test="self::text()">
<!-- Text -->
<xsl:element name="nodeName">
<xsl:value-of select="'text()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::text())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::text())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition + 1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<!-- Processing Instruction -->
<xsl:element name="nodeName">
<xsl:value-of select="'processing-instruction()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::processing-instruction())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::processing-instruction())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition + 1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::comment()">
<!-- Comment -->
<xsl:element name="nodeName">
<xsl:value-of select="'comment()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::comment())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::comment())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition + 1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="count(. | ../namespace::*) = count(../namespace::*)">
<!-- Namespace: -->
<xsl:variable name="apos">'</xsl:variable>
<xsl:element name="nodeName">
<xsl:value-of select="concat('namespace::*',
'[local-name() = ', $apos, local-name(), $apos, ']')"/>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$theResult"/>
</xsl:template>
---
www.simonwoodside.com



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



Current Thread