簡體   English   中英

通過XSLT和JavaScript排序XML文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM