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 > |