xsl-list
[Top] [All Lists]

Re: [xsl] Simple map and string-length(): unexpected behavior?

2019-06-08 02:26:11
Convoluted history here. The XPath 1.0 spec is:

<quote>
Function: number string-length(string?) <>
The string-length 
<https://www.w3.org/TR/1999/REC-xpath-19991116/#function-string-length> returns 
the number of characters in the string (see [3.6 Strings] 
<https://www.w3.org/TR/1999/REC-xpath-19991116/#strings>). If the argument is 
omitted, it defaults to the context node converted to a string, in other words 
the string-value 
<https://www.w3.org/TR/1999/REC-xpath-19991116/#dt-string-value> of the context 
node.

</quote>

(Yes, that's the entire spec). In 1.0, if you supplied something other than a 
string, it would be implicitly converted to a string by calling the string() 
function, by virtue of the rules for function calls. Recall also that 1.0 only 
had a context node, not a context item (without something like the "!" 
operator, there was no way the context item could be a number.)

In 2.0 the spec became:

<quote>
7.4.4 fn:string-length

fn:string-length() as xs:integer
fn:string-length($arg as xs:string?) as xs:integer
Summary: Returns an xs:integer equal to the length in characters of the value 
of $arg.

If the value of $arg is the empty sequence, the xs:integer 0 is returned.

If no argument is supplied, $arg defaults to the string value (calculated using 
fn:string() <https://www.w3.org/TR/xquery-operators/#func-string>) of the 
context item (.). If no argument is supplied and the context item is undefined 
an error is raised: [err:XPDY0002 
<http://www.w3.org/TR/xpath20/#ERRXPDY0002>]XP.

</quote>

Spot the difference.

I don't know if it was recognized at the time, but the way that is written 
means that string-length() and string-length(.) do different things. If the 
context item is a number, string-length() converts the number to a string, 
whereas string-length(.) gives you a type error unless XPath 1.0 compatibility 
mode is in force.

If (like other functions that take the context item as an implicit argument) 
the spec had simply said that the first argument defaults to "." (the context 
item), it would still have been backwards compatible with 1.0 in all cases when 
backwards compatibility was enabled, without introducing this anomaly.

Michael Kay
Saxonica


On 8 Jun 2019, at 01:52, Elisa Beshero-Bondar ebbondar(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

Dear XSL list,

We are perplexed by a discrepancy between applying the string-length() 
function directly to a numerical argument and using simple map to perform 
what we expected would be the same operation. string-length(5) returns an 
error, as expected. oXygen reports: "XPath failed due to: Required item type 
of first argument of fn:string-length() is xs:string; supplied expression (5) 
has item type xs:integer". eXist-db reports: "xs-integer(5) is not a sub-type 
of xs-string". 

When we use simple map, though, the behavior is different:

5 ! string-length() returns a string-length of 1

05 ! string-length() returns a string-length of 2

0.5 ! string-length() returns a string-length of 3 

00.5 ! string-length returns a string-length of 3  

05 ! string-length() returns a string-length of 1

Can someone please explain why simple-map does not raise the type error that 
we see when we write the numerical argument directly inside the function 
parentheses?

Thanks for your help!
Elisa
-- 
Elisa Beshero-Bondar, PhD
Associate Professor of English
University of Pittsburgh at Greensburg
Humanities Division
150 Finoli Drive
Greensburg, PA  15601  USA
E-mail: ebb8(_at_)pitt(_dot_)edu <mailto:ebb8(_at_)pitt(_dot_)edu>
XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/293509> (by 
email <>)
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>