Re: [Xsltforms-support] XPath and whitespace
Brought to you by:
alain-couthures
|
From: Alain C. <ala...@ag...> - 2016-04-14 16:55:26
|
Michael,
I have improved the XPath parser accordingly and I suggest you to patch
1.0RC2 for an XSLT template named "getLocationPath", at its end:
Please replace:
<xsl:choose>
<xsl:when test="$i = '0'"><xsl:value-of
select="concat($l,'.',$r)"/></xsl:when>
<xsl:otherwise>
<xsl:variable name="s3"
select="substring($s,number(substring-before($i,'.'))+1)"/>
<xsl:variable name="p">
<xsl:choose>
<xsl:when test="substring($s3,1,1)
= '['">
<xsl:variable
name="t"><xsl:call-template name="getPredicates"><xsl:with-param
name="s" select="substring($s3,2)"/></xsl:call-template></xsl:variable>
<xsl:value-of
select="concat(substring-before($t,'.'),'.',substring-after($t,'.'),')')"/>
</xsl:when>
<xsl:when
test="substring-after($i,'.') = ''">0.</xsl:when>
<xsl:otherwise>0.)</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="getLocationPath">
<xsl:with-param name="s"
select="substring($s3,number(substring-before($p,'.'))+1)"/>
<xsl:with-param name="r"
select="concat($r,substring-after($i,'.'),substring-after($p,'.'))"/>
<xsl:with-param name="l"
select="$l+number(substring-before($i,'.'))+number(substring-before($p,'.'))"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
by:
<xsl:choose>
<xsl:when test="$i = '0'"><xsl:value-of
select="concat($l,'.',$r)"/></xsl:when>
<xsl:otherwise>
<xsl:variable name="s3"
select="substring($s,number(substring-before($i,'.'))+1)"/>
<xsl:variable name="c3"
select="substring(normalize-space($s3),1,1)"/>
<xsl:variable name="i3"
select="string-length(substring-before($s3,$c3))"/>
<xsl:variable name="s4"
select="concat($c3,substring-after($s3,$c3))"/>
<xsl:variable name="p">
<xsl:choose>
<xsl:when test="$c3 = '['">
<xsl:variable
name="t"><xsl:call-template name="getPredicates"><xsl:with-param
name="s" select="substring($s4,2)"/></xsl:call-template></xsl:variable>
<xsl:value-of
select="concat(substring-before($t,'.'),'.',substring-after($t,'.'),')')"/>
</xsl:when>
<xsl:when test="substring-after($i,'.') =
''">0.</xsl:when>
<xsl:otherwise>0.)</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="s5"
select="substring($s4,number(substring-before($p,'.'))+1)"/>
<xsl:variable name="c5"
select="substring(normalize-space($s5),1,1)"/>
<xsl:variable name="i5"
select="string-length(substring-before($s5,$c5))"/>
<xsl:call-template name="getLocationPath">
<xsl:with-param name="s"
select="concat($c5,substring-after($s5,$c5))"/>
<xsl:with-param name="r"
select="concat($r,substring-after($i,'.'),substring-after($p,'.'))"/>
<xsl:with-param name="l"
select="$l+number(substring-before($i,'.'))+$i3+number(substring-before($p,'.'))+$i5"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
Thank you for your feedback!
--Alain
Le 13/04/2016 01:33, C. M. Sperberg-McQueen a écrit :
> Over the last few years, as I've used XSLTForms, I have occasionally
> stumbled over the way whitespace appears to be handled in XPath
> expressions. The XPath specs are not always as clear about it as they
> might be (in the sense that if you just look at the EBNF rules, you'll
> never discover the rule), but the general rule is that whitespace is
> allowed between any two tokens of an XPath.
>
> The last paragraph of section 1 in XPath 1.0 [1] says
>
> Expressions are parsed by first dividing the character string to be
> parsed into tokens and then parsing the resulting sequence of
> tokens. Whitespace can be freely used between tokens. The
> tokenization process is described in [3.7 Lexical Structure].
>
> [1]http://www.w3.org/TR/xpath/#section-Introduction
>
> In XPath 2.0 [2], the clearest statement is in the definition of
> 'ignorable whitespace':
>
> [Definition: Ignorable whitespace consists of any whitespace
> characters that may occur between terminals, unless these characters
> occur in the context of a production marked with aws:explicit
> annotation, in which case they can occur only where explicitly
> specified (see A.2.4.2 Explicit Whitespace Handling).] Ignorable
> whitespace characters are not significant to the semantics of an
> expression. Whitespace is allowed before the first terminal and
> after the last terminal of a module. Whitespace is allowed between
> any two terminals. Comments may also act as "whitespace" to prevent
> two adjacent terminals from being recognized as one.
>
> [2]http://www.w3.org/TR/xpath20/#IgnorableWhitespace
>
> As I understand these rules, they have the consequence that
>
> .[not(instance('trial')/self::trial/*[name(.)=name(current())])]
> ]
> is grammatically the same as
>
> .[not(
> instance('trial')
> /self::trial
> /*
> [name(.) = name(current())]
> )
> ]
>
> Since I found the first one a bit convoluted, as I was constructing
> it, I really wanted to use the second form, which I find slightly
> easier to check for correctness.
>
> But the XPath parser used in XSLTForms (at least through 1.0RC2)
> seems to take the view that whitespace can be ignored only inside
> predicates. So to make the expression just given work in a form, I end
> up rewriting it without whitespace, or (if I insist on breaking the
> expression into multiple lines) in some form like
>
> .[ not(instance('trial')/self::trial/*[
> name(.) = name(current())])
> ]
> ]
>
> Is there any chance of an improvement in this situation? In
> principle, it's easy to work around; in practice, I forget the
> limitation again and again, when I'm working with long convoluted
> binding expressions, and end up with mysterious failures until I
> remember "oh, yes, I'm not allowed to have whitespace where I want".
> So fixing this would definitely make XSLTForms easier to use, for at
> least this one user.
>
> best,
>
> Michael Sperberg-McQueen
>
|