xsl-list
[Top] [All Lists]

xpath confusion (compound xpath)

2003-01-18 13:40:37
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



<Prev in Thread] Current Thread [Next in Thread>