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>
</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="thepath"/>
<xsl:text> NO</xsl:text>
<xsl:text>
</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