xsl-list
[Top] [All Lists]

Re: [xsl] xsl:if test = empty string, returns true

2012-05-13 16:17:27
Change it to the following to work:



      <xsl:function name="me:metadata" as="xsd:string?">

Indeed does!

And, you are looking for the adjacent node (which in your example is a text 
node), rather than the adjacent element (unless you are invoking saxon with 
the option to strip white-space text nodes from your input, in which case 
that is not true).

No I wasn't invoking saxon with such option, but did try nevertheless to use:

        <xsl:strip-space elements="plist dict"/>

and

        <xsl:strip-space elements="*"/>

Still, even with or without those, if I assigned a value to the string, the 
function did capture it and showed it in the output of my original stylesheet 
in either case. Why does following::node()[1] return the string's value in both 
cases then?

BTW, I very rarely ever have to address text() nodes

Well, I did that to try to force the function to return a string instead of a 
tree :-/ As you can see there are still concepts of XSL that I am not quite 
grasping yet.

       <xsl:template name="main" exclude-result-prefixes="me">

Why not put the exclude-result-prefixes on the document element?

That was just a mistake of copy-pasting when creating the test XSLT for the ML. 
Thanks for pointing it out.

I hope the additional comments are considered helpful and not critical.  I 
wouldn't want readers of the archive to use text() as you are.

More than appreciated. I simply wanted to discourage answers that focused on 
issues that did not address my main question. Please excuse me for the 
prejudice.


El 13/05/2012, a las 22:24, G. Ken Holman escribió:

At 2012-05-13 22:03 +0200, Jorge wrote:
According to http://www.w3.org/TR/xpath/#section-Boolean-Functions:

The boolean function converts […] a string to true if and only if its 
length is non-zero.

My XSLT 2.0 stylesheet has an xsl:if element testing a function that seems 
to be returning a string of length zero, and yet the test evaluates to true. 
I am processing the stylesheet with Saxon-HE 9.2.1.2J with this command line:

java -jar saxon/saxon9he.jar -it:main -xsl:./test.xsl

This is the stylesheet `test.xsl`:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:me="null">

      <xsl:variable name="PLIST" select="'./test.plist'"/>

      <!-- Load external plist into variable -->
      <xsl:variable name="metadata" select="document(iri-to-uri($PLIST))"/>

      <!-- Function to fetch value of a key-string pair in plist -->
      <xsl:function name="me:metadata">

Not having added an as= constraint, you are creating a temporary tree with a 
text node child.

Change it to the following to work:

      <xsl:function name="me:metadata" as="xsd:string?">


              <xsl:param name="label"/>
              <xsl:value-of 
select="normalize-space($metadata/plist/dict/key[text()=$label]/following::node()[1]/text())"/>

Note that the following:: axis looks all the way to the end of the document.  
And, you are looking for the adjacent node (which in your example is a text 
node), rather than the adjacent element (unless you are invoking saxon with 
the option to strip white-space text nodes from your input, in which case 
that is not true).  So I suggest using following-sibling::* in case you do 
end up with white-space text nodes.

BTW, I very rarely ever have to address text() nodes and the above would be 
better written as:

<xsl:value-of 
select="normalize-space($metadata/plist/dict/key[.=$label]/following-sibling::*[1])"/>

This is not just a matter of style ... consider how your code would not work 
when there is more than one text node:

 <key>test<!--used to end here-->key</key>


      </xsl:function>

      <xsl:output method="text" encoding="UTF-8"/>

      <xsl:template name="main" exclude-result-prefixes="me">


Why not put the exclude-result-prefixes on the document element?


              <xsl:choose>
                      <xsl:when test="me:metadata('testkey')">
testkey = "<xsl:value-of select="me:metadata('testkey')"/>"
testkey's length = <xsl:value-of 
select="string-length(me:metadata('testkey'))"/>
                      </xsl:when>
                      <xsl:otherwise>
                              "testkey" is empty or does not exist.
                      </xsl:otherwise>
              </xsl:choose>
      </xsl:template>

</xsl:stylesheet>
...
Any idea why the test evaluates to true?

Because the returned data type of the function value is a temporary tree and 
while it may or may not have a text node child, the document node in the tree 
makes the test true().

Please note that I am not wondering whether the way I wrote the stylesheet 
is the most appropriate way to do what it is supposed to do, but why the 
test is evaluating to true.

Nevertheless I hope the additional comments are considered helpful and not 
critical.  I wouldn't want readers of the archive to use text() as you are.

. . . . . . . . Ken

--
Public XSLT, XSL-FO, UBL and code list classes in Europe -- Oct 2012
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour lecture: http://www.CraneSoftwrights.com/links/udemy.htm
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/s/
G. Ken Holman                   
mailto:gkholman(_at_)CraneSoftwrights(_dot_)com
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--