从用户定义的函数返回QName

Mar*_*rot 5 xslt saxon xslt-2.0

我试图将WSDL定义转换为另一种格式以进行进一步处理,但是遇到了一个问题。我似乎无法从函数返回QName值,而无需将它们转换为字符串。

我将文件缩减为以下内容,同时保留了错误行为。原始函数应该使用target-namespace包含<xs:schema>或中的属性来转换非前缀值<wsdl:definitions>

XSLT文档示例:

<?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>
Run Code Online (Sandbox Code Playgroud)

输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
Run Code Online (Sandbox Code Playgroud)

预期结果:

<?xml version="1.0" encoding="UTF-8"?>
<QName>
    <prefix>xs</prefix>
    <local>string</local>
    <namespace>http://www.w3.org/2001/XMLSchema</namespace>
</QName>
Run Code Online (Sandbox Code Playgroud)

运行上面的代码时,Saxon 9.3.0.5 XSLT处理器正在停止,并出现错误:

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

看来引擎首先将QName转换为字符串,然后尝试将其转换回QName,这会失败。如果删除两者as="xs:QName",则会出现以下错误:

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

如何从函数返回QName?

这是Saxon XSLT处理器中的错误,还是我对XSLT误解了?

是否有任何XSLT引擎能够处理上述文件?

Dim*_*hev 4

问题就在这里

<xsl:value-of select="resolve-QName($name,$element)"/>
Run Code Online (Sandbox Code Playgroud)

这会根据返回的 QName 生成一个文本节点(字符串)resolve-QName()

然而,my:resolve-QName2被声明为 of 类型xs:QName——而不是 of 类型xs:string,这会导致正确报告的错误。

解决方案

将上面的内容替换为:

<xsl:sequence select="resolve-QName($name,$element)"/>
Run Code Online (Sandbox Code Playgroud)

现在当修正后的转换时

<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>
Run Code Online (Sandbox Code Playgroud)

应用于提供的 XML 文档

<definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
Run Code Online (Sandbox Code Playgroud)

产生了想要的正确结果

<QName>
   <prefix>xs</prefix>
   <local>string</local>
   <namespace>http://www.w3.org/2001/XMLSchema</namespace>
</QName>
Run Code Online (Sandbox Code Playgroud)

  • 当我们介绍 XSLT 2.0 中的数据模型更改时,我们认真考虑使用 (xsl:value-of, xsl:text) 作为现在称为 (xsl:sequence, xsl:value-of) 的指令,但向后兼容性的影响是太严厉了。所以,是的,请记住这两条指令的作用并不完全像它们的名字所暗示的那样。 (3认同)