0

背景:我需要在 Web 浏览器中使用 XSLT 2.0 来执行另一个 XSLT 2.0 转换 - 这将用于 XSLT 处理器的测试驱动程序。处理器的 JavaScript API 允许您构建一个文字命令对象,该对象作为参数传递给运行函数以执行转换。

从 JavaScript 构建命令对象非常简单,但是从 XSLT 我需要使用内置的 JavaScript 扩展和用户定义的 JavaScript 函数来将 XSLT 数据转换为 JavaScript 对象。XPath 2.0 使用项目序列存在一个问题,但不允许使用序列序列。我当前使用的方法显示在以下 XSLT 片段中,它声明了一个变量cmd

用于创建 JavaScript 对象的 XSLT 代码

等效的 JavaScript 如下所示,供参考:

var cmd= {
            initialTemplate: initialTemplate,
            stylesheet:      stylesheet,
            source:          'uk-maps.xml',
            parameters:      {
                                            country:    'UK',
                                            city:       'Cheltenham',
                                            color:       [28, 329, 767]
                             }
};

跨入 JavaScript 时,XSLT 处理器将序列转换为 JavaScript 对象数组。用户定义的 JavaScript 函数js:object处理数组并为奇数项创建属性,并从相应的偶数项中分配属性值。可以递归调用js:object函数将JavaScript 对象分配给新对象的属性。我的另一个解决方法是用户定义的 js:array 函数,它将 XPath 序列包装在 JavaScript 对象中,以允许将其作为序列项嵌入。js:object函数必须检测并解开这些 js:array 对象。

所以,问题是:这是在 XSLT 2.0 中构建 JavaScript 文字对象的一种方法,但它涉及一些可能并不适合所有人的变通方法。还可以使用哪些其他方法?也许我应该使用现有的将 XML 转换为文字 JavaScript 对象的 JavaScript 库函数?XSLT 3.0 映射(此处理器中尚不可用)会提供更好的解决方案吗?提议的 JSON / XSLT 兼容性功能取得了哪些进展?如果js:objectjs:array是处理器内置的扩展函数会更好吗?

4

2 回答 2

1

这是处理此类任务的一种方法

给定以下 XML 文档:

<t xmlns:js="js:aux">
 <initialTemplate>
   <js:var>initialTemplate</js:var>
 </initialTemplate>
 <stylesheet>
   <js:var>stylesheet</js:var>
 </stylesheet>
 <source>uk-maps.xml</source>
 <parameters>
  <js:object>
          <country>UK</country>
          <city>Cheltenham</city>
          <colours>
            <js:array>
                   <js:num>28</js:num>
                   <js:num>329</js:num>
                   <js:num>767</js:num>
           </js:array>
          </colours>
  </js:object>
 </parameters>
</t>

这种转变

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:js="js:aux">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  {
    <xsl:apply-templates/>
   }
 </xsl:template>

 <xsl:template match="*/*[not(self::js:*)]">
   <xsl:variable name="vNotLast" select="exists(following-sibling::*[1])"/>

         <xsl:sequence select="name(), ':&#9;'"/>
         <xsl:apply-templates/>

         <xsl:sequence select="','[$vNotLast], '&#xA;'"/>
 </xsl:template>

 <xsl:template match="*[not(self::js:*)]/text()">
  <xsl:sequence select='concat("&apos;", ., "&apos;")'/>
 </xsl:template>

 <xsl:template match="js:object">
  {
    <xsl:apply-templates/>
  }
 </xsl:template>

 <xsl:template match="js:array">
  [
    <xsl:apply-templates/>
  ]
 </xsl:template>

 <xsl:template match="js:array/*">
  <xsl:next-match/>

  <xsl:variable name="vNotLast" select="exists(following-sibling::*[1])"/>
  <xsl:sequence select="','[$vNotLast]"/>
 </xsl:template>
</xsl:stylesheet>

产生

  {
    initialTemplate :   initialTemplate, 
 stylesheet :   stylesheet, 
 source :    'uk-maps.xml' , 
 parameters :   
  {
    country :    'UK' , 
 city :  'Cheltenham' , 
 colours :  
  [
    28,329,767
  ]


  }


   }

然后这个结果只需要提供给 Javascripteval()函数。

于 2012-05-05T18:06:45.713 回答
0

我目前的想法是最初使用问题中概述的带有 XPath 2.0 的原始解决方案。然后,当处理器支持 XPath 3.0 映射时,可以使用新的映射构造函数,因此等效代码为:

<xsl:variable
name="cmd"
select="
map {
       'initialTemplate' := $initialTemplate;
       'stylesheet'      := $stylesheet;
       'source'          := 'uk-maps.xml';
       'parameters'      := map {
                                    'country'  := 'UK';
                                    'city'     := 'Cheltenham';
                                    'color'    := (28, 329, 767);

                                };
};
"/>

我假设映射可以将序列作为值项处理,它还可以将其他映射作为值项包含在内,因此对 JavaScript 函数的调用将是唯一的非标准部分:

<xsl:variable name="result" as="document-node()" select="js:run($cmd)"/>
于 2012-05-06T11:31:31.303 回答