我正在尝试使用Javascript转换XSLT并尝试将其用于Chrome和IE浏览器。输入页面为a.html
。它在IE中运行良好(原生/兼容模式)但在Chrome中无法正常工作,即不会使用选项创建下拉列表。
在chrome中,如果我打开data.xml
,其中包含:
<?xml-stylesheet type="text/xsl" href="render.xslt" ?>
直接在铬中,它变得非常精细。但是如果我尝试使用XSLTProcessor来做同样的事情,它就不起作用了。具体来说,document
功能不起作用。你能帮忙吗?
我的代码如下。
使用Javascript:
var MSXML2_DOMDocument_6 = "MSXML2.DOMDocument.6.0";
function tranform(xml, xsl) {
if (window.ActiveXObject || "ActiveXObject" in window) {
var xmlSerializer = new XMLSerializer();
var xmlString = xmlSerializer.serializeToString(xml);
var xslString = xmlSerializer.serializeToString(xsl);
var xsl = new ActiveXObject(MSXML2_DOMDocument_6);
xsl.setProperty("AllowXsltScript", true);
xsl.setProperty("AllowDocumentFunction", true);
xsl.resolveExternals = true;
xsl.async = false;
xsl.loadXML(xslString);
var xml = new ActiveXObject(MSXML2_DOMDocument_6);
xml.resolveExternals = true;
xml.preserveWhiteSpace = true;
xml.async = false;
xml.loadXML(xmlString);
xml.resolveExternals = true;
ex = xml.transformNode(xsl);
document.getElementById("example").innerHTML = ex;
} else if (document.implementation && document.implementation.createDocument) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
document.getElementById("example").appendChild(resultDocument);
}
}
function loadXMLDoc() {
$.ajax({
method: "GET",
url: "data.xml",
dataType: "xml"
}).then(function (xml) {
console.log("done xml")
$.ajax({
method: "GET",
url: "render.xslt",
dataType: "xml"
}).then(function (xsl) {
console.log("done xsl")
tranform(xml, xsl)
})
},
function (e) {
console.log("Got error in xml", e.status)
})
}
$(loadXMLDoc)
富/ B.XML:
<dropdowns>
<dropdown name="xyz">
<option value="I">Info</option>
<option value="C">Category</option>
</dropdown>
</dropdowns>
data.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="render.xslt" ?>
<catalog name="xyz" />
a.html:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="jquery-3.3.1.js"></script>
<title>Document</title>
</head>
<body>
<div id="example"></div>
<script src="b.js"></script>
</body>
</html>
render.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="util.xslt" />
<xsl:output method="html"></xsl:output>
<xsl:template match="/">
<h1>
<xsl:value-of select="/catalog/@name"></xsl:value-of>
</h1>
<xsl:call-template name="dropdown">
<xsl:with-param name="listname">xyz</xsl:with-param>
<xsl:with-param name="value" select="/catalog/@name"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
util.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"></xsl:output>
<xsl:template name="dropdown">
<xsl:param name="listname"/>
<xsl:param name="value"/>
<select>
<xsl:for-each select="document('foo/b.xml')/dropdowns/dropdown[@name=$listname]/option">
<option>
<xsl:attribute name="value">
<xsl:value-of select="@value"/>
</xsl:attribute>
<xsl:value-of select="."/>
</option>
</xsl:for-each>
</select>
</xsl:template>
</xsl:stylesheet>
对不起,成为MVE的例子有点长,但它已经完成了。
如果需要澄清,请告诉我。
答案 0 :(得分:0)
一般来说,整个方法都是关于嵌套模板的 这已在此处得到解答:How to traverse a nested XML structure using templates
以下是关于问题下方评论的一些问题和说明。
调整了本地服务器,它将文件util.xslt
作为内容类型text/css
提供,就像chrome而不是application/xslt+xml
所期望的那样,脚本仍然无法按预期工作。因此,还有另一个与chrome相关的问题。
有趣的是,有两个xslt文档,而其中一个由chrome application/xslt+xml
转移和接受,但另一个仅作为text/xml
或text/xsl
(是的,两者都是被chrome接受,我试过了。)
因此interesting post about versions of xml / xslt对此问题可能没用。
以下是控制台消息:
使用以下行完成服务器的调整,如果请求的文件名具有后缀Content-Type
并且预期的mime-type为{{},则更改xslt
(mime-type) 1}}:
text/css
<强>火狐强>
值得注意的是,firefox完全隐藏了<If "%{REQUEST_FILENAME} =~ m#\.xslt$# && %{HTTP:Accept} =~ m#^text\/css#">
Header set "Content-Type" "text/css"
</If>
网络面板:
此外,Firefox接受ActiveXObject和XSLTProcessor两种方法。根据JavaScript中的逻辑,默认设置为ActiveXObject,该版本在下拉列表的动画方面看起来也更平滑。
当xml-version设置为1.1时,Firefox正在抱怨,因此玩游戏 版本号可能无助于提高浏览器兼容性。
答案 1 :(得分:0)
我找到了解决此问题的解决方法 [1] 。
在Chrome中,<xsl:import>
在使用Javascript进行转换时可以正常工作。因此,我将每个<xsl:choose>
标记的XML转换为带有<xsl:when>
的XSL dropdown
。
更新util.xslt
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"></xsl:output>
<xsl:template name="dropdown">
<xsl:param name="listname"/>
<xsl:param name="value"/>
<select>
<xsl:choose>
<xsl:when name="$listname='xyz'">
<option value="I">Info</option>
<option value="C">Category</option>
</xsl:when>
</xsl:choose>
</select>
</xsl:template>
</xsl:stylesheet>
1。我同意这不是一个非常好的解决方法,当然也不是一个普遍的解决方法。如果有人有更好的解决方案,请将其作为答案发布。
答案 2 :(得分:0)
这是已知问题,自2009年开始启用。此外,Chrome团队也没有任何计划来修复它,他们正计划从Chrome中删除它的支持(不确定何时)。但是这个问题有一个解决方法。将xml数据转换为xslt,然后将其导入样式表。
所以你的javaScript代码将保持不变。
foo / b.xml将变为foo / b.xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template name="dropdowns">
<xsl:param name="listname"/>
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="$listname='xyz'">
<xsl:call-template name="option">
<xsl:with-param name="value">I</xsl:with-param>
<xsl:with-param name="label">Info</xsl:with-param>
<xsl:with-param name="selectedValue" select="$value"/>
</xsl:call-template>
<xsl:call-template name="option">
<xsl:with-param name="value">C</xsl:with-param>
<xsl:with-param name="label">Category</xsl:with-param>
<xsl:with-param name="selectedValue" select="$value"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="option">
<xsl:param name="label"/>
<xsl:param name="value"/>
<xsl:param name="selectedValue"/>
<option value="{$value}">
<xsl:if test="$value = $selectedValue">
<xsl:attribute name="selected">selected</xsl:attribute>
</xsl:if>
<xsl:value-of select="$label"/>
</option>
</xsl:template>
</xsl:stylesheet>
util.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="foo/b.xslt" />
<xsl:output method="html" />
<xsl:template name="dropdown">
<xsl:param name="listname"/>
<xsl:param name="value"/>
<select>
<xsl:call-template name="dropdowns">
<xsl:with-param name="listname" select="$listname"/>
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
</select>
</xsl:template>
</xsl:stylesheet>
render.xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="util.xslt" />
<xsl:output method="html"></xsl:output>
<xsl:template match="/">
<h1>
<xsl:value-of select="/catalog/@name"></xsl:value-of>
</h1>
<xsl:call-template name="dropdown">
<xsl:with-param name="listname">xyz</xsl:with-param>
<xsl:with-param name="value">C</xsl:with-param>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
通过这些更改,您可以在您的页面中创建下拉菜单,这将在IE和Chrome中都有效。