我正在尝试进行XSL转换。
但是,每当引用带有文档片段的变量时,转换似乎都会失败。
我创建了一个JSFiddle来演示此问题。示例中的XML是允许XSLT运行的虚拟文档。
我在做什么错了?
Javascript:
var xml = [
'<p xmlns="http://www.w3.org/1999/xhtml">',
'<\/p>'
].join('\n');
var xsl = [
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">',
'<xsl:variable name="xmlVar">',
'<aaaa value="It works"\/>',
'<\/xsl:variable>',
'<xsl:template match="\/">',
'<ROOT>',
//works ok after commenting out
'<xsl:value-of select="$xmlVar\/aaaa\/@value"\/>',
'<\/ROOT>',
'<\/xsl:template>',
'<\/xsl:stylesheet>'
].join('\n');
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(xml, 'application/xml');
var xslDoc = domParser.parseFromString(xsl, 'application/xml');
var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xslDoc);
try{
var result = xsltProc.transformToFragment(xmlDoc, document);
} catch(exc) {
document.getElementById('error').innerHTML = exc;
}
function encodeStr(rawStr) { return rawStr.replace(/[\u00A0-\u9999<>\&]/gim,
function(i){
return '&#'+i.charCodeAt(0)+';'
});
}
document.getElementById('xslText').innerHTML = encodeStr(xsl);
document.getElementById('result').innerHTML = encodeStr((new XMLSerializer).serializeToString(result));
HTML:
<pre id='xslText'>
</pre>
<pre id='result'>
</pre>
<pre id='error'>
</pre>
答案 0 :(得分:1)
在XSLT 1.0中,您需要使用扩展功能,例如exsl:node-set
(http://exslt.org/exsl/functions/node-set/index.html),将类型为结果树片段(https://www.w3.org/TR/xslt-10/#section-Result-Tree-Fragments)的变量值转换为要设置的节点集。能够在节点上使用XPath,例如
var xml = [
'<p xmlns="http://www.w3.org/1999/xhtml">',
'<\/p>'
].join('\n');
var xsl = [
'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:exsl="http://exslt.org/common" xmlns:msxml="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="exsl msxml">',
'<xsl:variable name="xmlVar">',
'<aaaa value="It works"/>',
'<\/xsl:variable>',
'<xsl:template match="/">',
'<div>',
'<xsl:choose><xsl:when test="function-available(\'exsl:node-set\')"><xsl:value-of select="exsl:node-set($xmlVar)/aaaa/@value"/><\/xsl:when><xsl:when test="function-available(\'msxml:node-set\')"><xsl:value-of select="msxml:node-set($xmlVar)/aaaa/@value"/><\/xsl:when><\/xsl:choose>',
'<\/div>',
'<\/xsl:template>',
'<\/xsl:stylesheet>'
].join('\n');
var domParser = new DOMParser();
var xmlDoc = domParser.parseFromString(xml, 'application/xml');
var xslDoc = domParser.parseFromString(xsl, 'application/xml');
var xsltProc = new XSLTProcessor();
xsltProc.importStylesheet(xslDoc);
try{
var result = xsltProc.transformToFragment(xmlDoc, document);
document.getElementById('result').appendChild(result);
} catch(exc) {
document.getElementById('error').innerHTML = exc;
}
<pre id='xslText'>
</pre>
<pre id='result'>
</pre>
<pre id='error'>
</pre>
就跨浏览器与客户端XSLT 1的兼容性而言,缺点是Microsoft在IE和Edge中使用MSXML 3或6提供XSLT支持,但不幸的是,MSXML具有其专有的命名空间来支持这种扩展功能,而不是支持EXSLT。
小提琴已更新为http://jsfiddle.net/29pwf84c/14/。