[英]Sorting XML file via XSLT and JavaScript
我目前正在嘗試實現一個功能,以按其節點之一的屬性對XML文件進行排序。
可行的方法似乎是使用XSLT轉換XML文件,並通過研究使我設法將一個有效的XSLT文件放在一起(在某些在線驗證器中進行了驗證,輸出與預期的一樣)。
獲得所需的結果后,我開始實現JavaScript函數,以在每次需要時自動執行此操作。 最終,將使用XML文件中的數據創建一個圖表(amCharts)。 為了正確地生成該圖表,必須對數據進行排序。
現在,一切似乎都在語法上起作用,但是,XSLTProcessor和/或XMLSerializer似乎在解析/組合XML和XLST文件時遇到問題。
奇怪的是,Firefox也引發錯誤: 組件返回失敗代碼:0x80600001 [nsIXSLTProcessor.importStylesheet]
Chrome似乎沒有這個問題。
但這不是主要問題。 生成的結果包含一個基本的HTML頁面,該頁面說有錯誤,但是沒有給出確切的錯誤描述/位置/解釋。
我希望可以在這里看到排序后的XML文件,就像在線XML / XSLT驗證器中一樣,該驗證器具有相同的XML / XSLT內容輸入內容。
是否有人對這個問題的根源有任何想法? 將不勝感激對此的任何提示和/或解決方案。
最好的祝福,
大扎
編輯
在對生成的頁面上的“文檔末尾的額外內容”錯誤進行了更深入的研究(並在我發布OP時忽略了該錯誤)之后,似乎錯誤發生在包含多個根元素的情況下XML文件,這顯然是錯誤的。
但是,源XML文件沒有多個根節點,並且完全有效。
這使我相信,盡管在XSLT驗證程序中看起來不錯,但是對源文件的XSLT重新排序/排序並未按預期進行。 我猜想它會產生多個根節點,而不只是重新排序根節點內的項目節點?
不幸的是,我不是XSLT的專家,所以如果有更詳細的知識的人尤其可以看一下XSLT代碼,那就太好了。
編輯2
我想我可以通過稍微更改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>
首先,我將重新設置您的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,那么這是一個單獨的問題!)
但是,我認為這不再是您的XSLT的問題,而是與如何在瀏覽器中使用javascript進行轉換有關的問題。 您提供的代碼僅適用於Chrome和Firefox(我認為是Opera)。 IE不支持這些命令,而是擁有自己的方法。 更復雜的是,IE10及更高版本的功能與以前的版本不同!
無論如何,我轉到Internet Explorer 10(Windows 8)中的Object不支持屬性或方法“ transformNode”,並找到了一個不錯的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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.