6

I am trying to transform a WSDL definition into another format for further processing, but I ran into a problem. I can't seem to return QName-values from a function, without them being turned into a string.

I reduced the file to the following, while retaining the error behavior. The original function was supposed to translate non-prefixed values using the target-namespace attribute from the containing <xs:schema> or <wsdl:definitions>.

Example XSLT document:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:my="http://www.example.com/xslt"
    exclude-result-prefixes="#all" version="2.0">

    <xsl:output method="xml" indent="yes"/>

    <xsl:function name="my:resolve-QName2" as="xs:QName">
        <xsl:param name="name" as="xs:string"/>
        <xsl:param name="element" as="element()"/>
        <xsl:value-of select="resolve-QName($name,$element)"/>
    </xsl:function>

    <xsl:template match="/definitions">
        <xsl:variable name="qname" select="my:resolve-QName2('xs:string',.)" as="xs:QName"/>
        <QName>
            <prefix><xsl:value-of select="prefix-from-QName($qname)"/></prefix>
            <local><xsl:value-of select="local-name-from-QName($qname)"/></local>
            <namespace><xsl:value-of select="namespace-uri-from-QName($qname)"/></namespace>
        </QName>
    </xsl:template>
</xsl:stylesheet>

Input file:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"/>

Expected result:

<?xml version="1.0" encoding="UTF-8"?>
<QName>
    <prefix>xs</prefix>
    <local>string</local>
    <namespace>http://www.w3.org/2001/XMLSchema</namespace>
</QName>

When running the above code, the Saxon 9.3.0.5 XSLT processor is stopping with an error:

Required item type of result of function my:resolve-QName2() is xs:QName. Cannot convert string to type {xs:QName}

It seems the engine is first casting the QName into a string, and then trying to cast it back to QName, which fails. If I remove the two as="xs:QName", I get the following error:

Required item type of first argument of prefix-from-QName() is xs:QName. Cannot convert string to type {xs:QName}

How can I return a QName from a function?

Is this a bug in Saxon XSLT processor, or something I have misunderstood about XSLT?

Is there any XSLT engine that is able to process the above file?

Markus Jarderot
  • 86,735
  • 21
  • 136
  • 138

1 Answers1

4

The problem is here:

<xsl:value-of select="resolve-QName($name,$element)"/>

This produces a text node (string) from the QName that resolve-QName() returns.

However the my:resolve-QName2 is declared as of type xs:QName -- not of xs:string and this causes the correctly reported error.

Solution:

Replace the above with:

<xsl:sequence select="resolve-QName($name,$element)"/>

Now when the corrected transformation:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:my="http://www.example.com/xslt"
        exclude-result-prefixes="#all" version="2.0">

        <xsl:output method="xml" indent="yes"/>

        <xsl:function name="my:resolve-QName2" as="xs:QName">
            <xsl:param name="name" as="xs:string"/>
            <xsl:param name="element" as="element()"/>
            <xsl:sequence select="resolve-QName($name,$element)"/>
        </xsl:function>

        <xsl:template match="/definitions">
            <xsl:variable name="qname" select="my:resolve-QName2('xs:string',.)" as="xs:QName"/>
            <QName>
                <prefix><xsl:value-of select="prefix-from-QName($qname)"/></prefix>
                <local><xsl:value-of select="local-name-from-QName($qname)"/></local>
                <namespace><xsl:value-of select="namespace-uri-from-QName($qname)"/></namespace>
            </QName>
        </xsl:template>
</xsl:stylesheet>

is applied on the provided XML document:

<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"/>

the wanted, correct result is produced:

<QName>
   <prefix>xs</prefix>
   <local>string</local>
   <namespace>http://www.w3.org/2001/XMLSchema</namespace>
</QName>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • 1
    Ok. Always use `` instead of `` with functions. A bit counter-intuitive, but it works. – Markus Jarderot Feb 20 '12 at 06:38
  • @MizardX: Not only with functions. Use `` if you want to cause atomization / conversion to string, and/or if you want to use its `separator` attribute – Dimitre Novatchev Feb 20 '12 at 06:54
  • 3
    When we introduced the data model changes in XSLT 2.0 we seriously considered using (xsl:value-of, xsl:text) for the instructions that are now called (xsl:sequence, xsl:value-of), but the backwards compatbility implications were too severe. So, yes, try to remember that these two instructions don't do quite what their names might suggest. – Michael Kay Feb 20 '12 at 09:31