[英]Creating a JavaScript literal object – within XPath 2.0
背景:我需要在Web浏览器中使用XSLT 2.0来执行另一个XSLT 2.0转换-这将在XSLT处理器的测试驱动程序中使用。 用于处理器的JavaScript API使您可以构建文字命令对象,该命令对象作为参数传递给运行函数以执行转换。
从JavaScript构建命令对象非常简单,但是从XSLT开始,我需要使用内置的JavaScript扩展和用户定义的JavaScript函数将XSLT数据转换为JavaScript对象。 XPath 2.0可以处理项目序列,但是不允许序列序列,这是一个问题。 我当前使用的方法显示在以下XSLT代码段中,该代码段声明了变量cmd :
下面显示了等效的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文字对象的一种方法,但是它涉及一些可能并不适合所有人的解决方法。 可以使用其他什么方法? 也许我应该使用现有的JavaScript库函数将XML转换为文字JavaScript对象? XSLT 3.0映射(此处理器尚不可用)是否提供更好的解决方案? 提议的JSON / XSLT兼容性功能取得了什么进展? 如果将js:object和js:array扩展功能内置到处理器中会更好吗?
这是完成此类任务的一种方法 :
给定以下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(), ':	'"/>
<xsl:apply-templates/>
<xsl:sequence select="','[$vNotLast], '
'"/>
</xsl:template>
<xsl:template match="*[not(self::js:*)]/text()">
<xsl:sequence select='concat("'", ., "'")'/>
</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
]
}
}
然后,只需要将该结果提供给Javascript eval()
函数即可。
我当前的想法是,最初将原始解决方案与问题中概述的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)"/>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.