我目前正在尝试实现一个函数,通过其中一个节点的属性对XML文件进行排序。
要走的路似乎是使用XSLT来转换XML文件,并通过研究我设法将一个有效的XSLT文件放在一起(在一些在线验证器中验证,输出就像预期的那样)。
获得我想要的结果后,我开始实现JavaScript函数,以便在每次需要时自动执行此操作。最终将使用XML文件中的数据创建图表(amCharts)。要正确生成该图表,必须对数据进行排序。
现在一切似乎都在语法方面有效,但是,XSLTProcessor和/或XMLSerializer似乎在解析/组合XML和XLST文件时遇到了问题。
奇怪的是,Firefox也会抛出错误:组件返回失败代码:0x80600001 [nsIXSLTProcessor.importStylesheet]
Chrome似乎没有此问题。
但这不是主要问题。生成的结果包含一个基本的HTML页面,说明有错误,但没有给出确切的错误描述/位置/解释。
我希望在这里看到排序的XML文件,就像在线XML / XSLT验证器一样,它具有相同的输入XML / XSLT内容。
有没有人对这个问题的根源有所了解?非常感谢任何提示和/或解决方案。
最好的问候,
daZza
修改
在生成的页面上研究“文档末尾的额外内容”错误后更深入(并且在我发布OP时忽略了它),似乎错误是在有多个时触发的XML文件中的根元素,显然是错误的。
但是,源XML文件没有多个根节点,并且完全有效。
这让我相信源文件的XSLT重新排序/排序没有按预期完成,尽管它在XSLT验证器中看起来很好。 我想它会以某种方式生成多个根节点,而不是只重新排序根节点中的项节点?
不幸的是,我不是XSLT的专家,所以如果有更详细知识的人可以特别关注XSLT代码,那就太棒了。
EDIT2
我想我可能通过稍微更改XSLT查询来解决问题。我正在为Chrome和Firefox获得一个正确的输出,但IE仍然会抛出错误(我是否提到我讨厌跨浏览器兼容性?-.-)。
仍然需要进一步测试,但至少它是一个进步。仍然欣赏有关该主题的任何提示。
代码:
XML示例代码段(删除的内容,“”部分填入真实文件中):
<?xml version="1.0" encoding="utf-8"?>
<root>
<item Art="" LinkTitle="" Eindruck="" Bereich="" Unterbereich="" Priority="" Handlungsma_x00df_nahme="" Status_x0020_der_x0020_Ma_x00df_="" Aufwand="" Benefit="" Termin_x0020_der_x0020_Retrospek="" Produkt="" Release="" />
<item Art="" LinkTitle="" Eindruck="" Bereich="" Unterbereich="" Priority="" Handlungsma_x00df_nahme="" Status_x0020_der_x0020_Ma_x00df_="" Aufwand="" Benefit="" Termin_x0020_der_x0020_Retrospek="" Produkt="" Release="" />
</root>
XSLT文件
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:choose>
<xsl:when test="*[local-name()='item']">
<xsl:apply-templates select="@* | node()">
<xsl:sort select="@Unterbereich" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="@* | node()" />
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
JavaScript功能
function sortXML()
{
var parser = new DOMParser();
// xml and xsl are correctly filled with the data from their appropriate files
// via AJAX GET requests earlier in the code
var domToBeTransformed = xml;
var xslt = xsl;
var processor = new XSLTProcessor();
processor.importStylesheet(xslt);
var newDocument = processor.transformToDocument(domToBeTransformed);
var serializer = new XMLSerializer();
var newDocumentXml = serializer.serializeToString(newDocument);
alert(newDocumentXml);
}
当前生成的文档(var newDocumentXml)
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<parsererror style="display: block; white-space: pre; border: 2px solid #c77; padding: 0 1em 0 1em; margin: 1em; background-color: #fdd; color: black">
<h3>This page contains the following errors:</h3>
<div style="font-family:monospace;font-size:12px">error on line 1 at column 1: Extra content at the end of the document</div>
<h3>Below is a rendering of the page up to the first error.</h3>
</parsererror>
</body>
</html>
答案 0 :(得分:0)
首先,我会重新设置您的XSLT以避免使用 xsl:choose 。如果您已经匹配属性或文本节点,则测试子元素是否存在没有意义。使用单独的模板可能更好(更干净,压痕更少)。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[*[local-name()='item']]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="node()">
<xsl:sort select="@Unterbereich" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
首先要注意的是,您在XSLT中指定了版本“2.0”。 Microsoft(以及IE)本身不支持XSLT 2.0。但是,在这种情况下,您没有使用任何XSLT 2.0功能,因此将其更改为XSLT 1.0应该不是问题(当然,如果您的实际XSLT确实需要使用2.0,那么这是一个完全独立的问题!)< / p>
但我认为这不再是你的XSLT的问题,而是更多关于如何在浏览器中使用javascript进行转换的问题。您提供的代码仅适用于Chrome和Firefox(我认为是Opera)。 IE不支持这些命令,并且有自己的方法。而且进一步复杂化,IE10及以上版本的做法与以前的版本不同!
无论如何,我前往Object doesn't support property or method 'transformNode' in Internet Explorer 10 (Windows 8)并找到了一个很好的JavaScript示例。尝试重新编写您的JavaScript:
function sortXML()
{
if (typeof (XSLTProcessor) != "undefined")
{
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
var resultDocument = xsltProcessor.transformToDocument(xml);
var serializer = new XMLSerializer();
var newDocumentXml = serializer.serializeToString(resultDocument);
alert(newDocumentXml);
}
else if (typeof (xml.transformNode) != "undefined")
{
var ex = xml.transformNode(xsl);
alert(ex);
}
else
{
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.load(xsl);
var xslt = new ActiveXObject("Msxml2.XSLTemplate");
xslt.stylesheet = xslDoc;
var xslProc = xslt.createProcessor();
xslProc.input = xml;
xslProc.transform();
alert(xslProc.output);
}
}