5

回答另一个线程(请参阅stackoverflow:生成 css 颜色方案)我遇到了下面的问题,其中不同的 xsl 引擎似乎需要不同的方法将结果树片段转换为节点集。

简化问题(但有关此背后的完整故事,请参见上面的链接),我希望有一个包含颜色值列表的内联树。由于这必须在 Xpath 表达式中使用,我必须从中创建一个节点集,专门用于 MSXML xx xsl 引擎(内置的 XML Spy 在解释包含构造为 rtf 的变量的 Xpath 表达式时比较容易)。
另一个线程stackoverflow:automating-exsltnode-set帮助了我。生成的节点集用于从输入 XML 创建新变量 rtf。
同样,当在 Xpath 表达式中使用新变量时,MSXML 会报错,因此我使用 node-set 函数从中创建一个节点集。
到目前为止一切顺利,MSXML xx 不再出错。
但是当我在 XML Spy built-in 或 Saxon 9he 中运行相同时,我得到另一个错误:似乎节点集函数是未知的:

Cannot find a matching 1-argument function named {urn:schemas-microsoft-com:xslt}node-set() in variable colorList

请注意,在此特定示例中不需要这种两步方法,但正如我所说,我简化了一些事情;我只是想知道如何编写一个适用于所有 xsl 引擎的 XSLT 1.0 转换。

我使用的 XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:std="http://whatever"
    xmlns:exslt="urn:schemas-microsoft-com:xslt"
    exclude-result-prefixes="std exslt">

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

    <std:colors>
        <color>#0000FF</color>
        <color>#FF0000</color>
    </std:colors>

    <xsl:variable name="colors" select="document('')/*/std:colors"/>

    <xsl:variable name="std:colorList">
        <xsl:for-each select="//testid">
            <xsl:variable name="pos" select="position() mod 2"/>
            <xsl:element name="color">
                <xsl:attribute name="testid"><xsl:value-of select="."/></xsl:attribute>
                <xsl:value-of select="$colors/color[$pos + 1]"/>
            </xsl:element>
        </xsl:for-each>
    </xsl:variable>

    <xsl:variable name="colorList" select="exslt:node-set($std:colorList)"/>

    <xsl:template match="/">
        <output>
            <xsl:copy-of select="$colorList/color"/>
        </output>
   </xsl:template>

</xsl:stylesheet>

输入文件:

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <defects>
    <testid>111</testid>
  </defects>
  <defects>
    <testid>999</testid>
  </defects>
</NewDataSet>

结果为 MSXML 3.0/4.0/6.0:

<?xml version="1.0" encoding="UTF-16"?>
<output>
<color testid="111">#FF0000</color>
<color testid="999">#0000FF</color>
</output>

Saxon9he 中的结果:

Cannot find a matching 1-argument function named {urn:schemas-microsoft-com:xslt}node-set()
in variable colorList

生成 XML Spy 内置 xsl 引擎:

Error in XPath expression
Unknown function - Name and number of arguments do not match any function signature in the static context - 'urn:schemas-microsoft-com:xslt:node-set'
4

5 回答 5

7

For processors other than MSXML, use the exslt:node-set() function. (http://www.exslt.org/). (It's a little odd to bind the exslt prefix to the Microsoft version of the function - that had me confused for a while!)

You can test which functions are available using function-available():

<xsl:choose>
  <xsl:when test="function-available('exslt:node-set')"...
  <xsl:when test="function-available('msxsl:node-set')"...

For Saxon-HE and other XSLT 2.0 processors you don't need any of these functions, so use

<xsl:when test="xsl:version='2.0'">
于 2012-03-23T10:57:29.720 回答
5

为了避免不得不做

 <xsl:choose>
 <xsl:when test="function-available('exslt:node-set')"...

每次需要时,您都可以为 xslt2 引擎(使用 xsl:function)和 msxml(使用 msxsl:script)定义exslt 节点集,然后在文档的其余部分中使用 exslt:node-set 函数。

http://dpcarlisle.blogspot.co.uk/2007/05/exslt-node-set-function.html

向您展示如何为 msxml 和 xslt2 引擎定义它,您可以 xsl:include 样式表

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:exslt="http://exslt.org/common"
        >

<xsl:function name="exslt:node-set">
  <xsl:param name="rtf"/>
  <xsl:sequence select="$rtf"/>
</xsl:function>

<xsl:stylesheet>

XSLT1 的前向兼容性规则意味着包含它是安全的,XSLT1 引擎将忽略它。

于 2012-03-23T12:21:40.377 回答
2

Microsoft 的 .NET XsltCompiledTransformXSLT 处理器支持 exslt:node-set()。

对于 MSXML,可以使用我自己的 EXSLT 函数子集的实现——对于 MSXML。您可以在此处找到详细说明和下载链接:

http://www.xml.com/pub/a/2003/08/06/exslt.html

于 2012-03-23T13:05:10.907 回答
1

Saxon 9 是 XSLT 2.0 处理器,XSLT 2.0 的主要改进之一是节点集和结果树片段之间的区别已经消失,您根本不需要任何扩展功能,因为您不需要强制不再有任何胁迫。因此,对于针对任何 XSLT 2.0 处理器的样式表,您应该简单地放弃使用类似扩展函数的任何尝试,然后样式表将起作用。如果您想使用 XSLT 1.0 和 2.0 处理器运行相同的样式表,那么我看到了一个问题,但我认为没有简单的解决方案。您将需要使用http://www.w3.org/TR/xslt#function-function-available和 system-property 来区分处理器和扩展功能的可用性。

于 2012-03-23T10:56:33.520 回答
-1

好吧,您无需任何检查即可轻松完成。只需遵循此处描述的模式:http: //dpcarlisle.blogspot.co.uk/2007/05/exslt-node-set-function.html

<xsl:stylesheet
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  exclude-result-prefixes="exslt msxsl">


<msxsl:script language="JScript" implements-prefix="exslt">
 this['node-set'] =  function (x) {
  return x;
  }
</msxsl:script>


<xsl:variable name="x">
  <y/>
</xsl:variable>

<xsl:template match="x">
  <html>
    <head><title>test exslt node set</title></head>
    <body>
      <xsl:apply-templates select="exslt:node-set($x)/*"/>
    </body>
  </html>
</xsl:template>

<xsl:template match="y">
  <p>node set!</p>
</xsl:template>

</xsl:stylesheet>

它绝对适用于 FF、Chrome 和 IE7+

于 2013-08-29T09:32:50.040 回答