網(wǎng)上商城網(wǎng)站建設(shè)方案互聯(lián)網(wǎng)優(yōu)化是什么意思
二十二、處理 XML
-
處理 XML
- XML 曾一度是在互聯(lián)網(wǎng)上存儲和傳輸結(jié)構(gòu)化數(shù)據(jù)的標準。XML 的發(fā)展反映了 Web 的發(fā)展,因為DOM 標準不僅是為了在瀏覽器中使用,而且還為了在桌面和服務(wù)器應(yīng)用程序中處理 XML 數(shù)據(jù)結(jié)構(gòu)。在沒有 DOM 標準的時候,很多開發(fā)者使用 JavaScript 編寫自己的 XML 解析器。自從有了 DOM 標準,所有瀏覽器都開始原生支持 XML、XML DOM 及很多其他相關(guān)技術(shù)。
-
瀏覽器對 XML DOM 的支持
- 因為很多瀏覽器在正式標準問世之前就開始實現(xiàn) XML 解析方案,所以不同瀏覽器對標準的支持不僅有級別上的差異,也有實現(xiàn)上的差異。DOM Level 3 增加了解析和序列化能力。不過,在 DOM Level 3制定完成時,大多數(shù)瀏覽器也已實現(xiàn)了自己的解析方案。
-
DOM Level 2 Core
- 正如第 12章所述,DOM Level 2增加了 document.implementation 的 createDocument()方法。有讀者可能還記得,可以像下面這樣創(chuàng)建空 XML 文檔:
let xmldom = document.implementation.createDocument(namespaceUri, root, doctype);
- 在 JavaScript 中處理 XML 時,root 參數(shù)通常只會使用一次,因為這個參數(shù)定義的是 XML DOM中 document 元素的標簽名。namespaceUri 參數(shù)用得很少,因為在 JavaScript 中很難管理命名空間。doctype 參數(shù)則更是少用。
- 要創(chuàng)建一個 document 對象標簽名為
<root>
的新 XML 文檔,可以使用以下代碼:let xmldom = document.implementation.createDocument("", "root", null); console.log(xmldom.documentElement.tagName); // "root" let child = xmldom.createElement("child"); xmldom.documentElement.appendChild(child);
- 這個例子創(chuàng)建了一個 XML DOM 文檔,該文檔沒有默認的命名空間和文檔類型。注意,即使不指定命名空間和文檔類型,參數(shù)還是要傳的。命名空間傳入空字符串表示不應(yīng)用命名空間,文檔類型傳入null 表示沒有文檔類型。xmldom 變量包含 DOM Level 2 Document 類型的實例,包括第 12 章介紹的所有 DOM 方法和屬性。在這個例子中,我們打印了 document 元素的標簽名,然后又為它創(chuàng)建并添加了一個新的子元素。
- 要檢查瀏覽器是否支持 DOM Level 2 XML,可以使用如下代碼:
let hasXmlDom = document.implementation.hasFeature("XML", "2.0");
- 實踐中,很少需要憑空創(chuàng)建 XML 文檔,然后使用 DOM 方法來系統(tǒng)創(chuàng)建 XML 數(shù)據(jù)結(jié)構(gòu)。更多是把XML 文檔解析為 DOM結(jié)構(gòu),或者相反。因為 DOM Level 2并未提供這種功能,所以出現(xiàn)了一些事實標準。
- 正如第 12章所述,DOM Level 2增加了 document.implementation 的 createDocument()方法。有讀者可能還記得,可以像下面這樣創(chuàng)建空 XML 文檔:
-
DOMParser 類型
- Firefox 專門為把 XML 解析為 DOM 文檔新增了 DOMParser 類型,后來所有其他瀏覽器也實現(xiàn)了該類型。要使用 DOMParser,需要先創(chuàng)建它的一個實例,然后再調(diào)用 parseFromString()方法。這個方法接收兩個參數(shù):要解析的 XML 字符串和內(nèi)容類型(始終應(yīng)該是"text/html")。返回值是 Document的實例。來看下面的例子:
let parser = new DOMParser(); let xmldom = parser.parseFromString("<root><child/></root>", "text/xml"); console.log(xmldom.documentElement.tagName); // "root" console.log(xmldom.documentElement.firstChild.tagName); // "child" let anotherChild = xmldom.createElement("child"); xmldom.documentElement.appendChild(anotherChild); let children = xmldom.getElementsByTagName("child"); console.log(children.length); // 2
- 這個例子把簡單的 XML 字符串解析為 DOM 文檔。得到的 DOM 結(jié)構(gòu)中
<root>
是 document 元素,它有個子元素<child>
。然后就可以使用 DOM 方法與返回的文檔進行交互。 - DOMParser 只能解析格式良好的 XML,因此不能把 HTML 解析為 HTML 文檔。在發(fā)生解析錯誤時,不同瀏覽器的行為也不一樣。Firefox、Opera、Safari 和 Chrome 在發(fā)生解析錯誤時,parseFromString()方法仍會返回一個 Document 對象,只不過其 document 元素是
<parsererror>
,該元素的內(nèi)容為解析錯誤的描述。下面是一個解析錯誤的示例:<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML Parsing Error: no element found Location: file:// /I:/My%20Writing/My%20Books/ Professional%20JavaScript/Second%20Edition/Examples/Ch15/DOMParserExample2.js Line Number 1, Column 7:<sourcetext><root> ------^</sourcetext></parsererror>
- Firefox 和 Opera 都會返回這種格式的文檔。Safari 和 Chrome 返回的文檔會把
<parsererror>
元素嵌入在發(fā)生解析錯誤的位置。早期 IE 版本會在調(diào)用 parseFromString()的地方拋出解析錯誤。由于這些差異,最好使用 try/catch 來判斷是否發(fā)生了解析錯誤,如果沒有錯誤,則通過 getElementsByTagName()方法查找文檔中是否包含<parsererror>
元素,如下所示:let parser = new DOMParser(), xmldom, errors; try { xmldom = parser.parseFromString("<root>", "text/xml"); errors = xmldom.getElementsByTagName("parsererror"); if (errors.length > 0) {throw new Error("Parsing error!"); } } catch (ex) { console.log("Parsing error!"); }
- 這個例子中解析的 XML 字符串少一個
</root>
標簽,因此會導(dǎo)致解析錯誤。IE 此時會拋出錯誤。Firefox 和 Opera 此時會返回 document 元素為<parsererror>
的文檔,而在 Chrome 和 Safari 返回的文檔中,<parsererror>
是<root>
的第一個子元素。調(diào)用 getElementsByTagName(“parsererror”)可適用于后兩種情況。如果該方法返回了任何元素,就說明有錯誤,會彈警告框給出提示。當然,此時可以進一步解析出錯誤信息并顯示出來。
- Firefox 專門為把 XML 解析為 DOM 文檔新增了 DOMParser 類型,后來所有其他瀏覽器也實現(xiàn)了該類型。要使用 DOMParser,需要先創(chuàng)建它的一個實例,然后再調(diào)用 parseFromString()方法。這個方法接收兩個參數(shù):要解析的 XML 字符串和內(nèi)容類型(始終應(yīng)該是"text/html")。返回值是 Document的實例。來看下面的例子:
-
XMLSerializer 類型
- 與 DOMParser 相對,Firefox 也增加了 XMLSerializer 類型用于提供相反的功能:把 DOM 文檔序列化為 XML 字符串。此后,XMLSerializer 也得到了所有主流瀏覽器的支持。
- 要序列化DOM文檔,必須創(chuàng)建XMLSerializer 的新實例,然后把文檔傳給serializeToString()方法,如下所示:
let serializer = new XMLSerializer(); let xml = serializer.serializeToString(xmldom); console.log(xml);
- serializeToString()方法返回的值是打印效果不好的字符串,因此肉眼看起來有點困難。
- XMLSerializer 能夠序列化任何有效的 DOM 對象,包括個別節(jié)點和 HTML 文檔。在把 HTML 文檔傳給 serializeToString()時,這個文檔會被當成 XML 文檔,因此得到的結(jié)果是格式良好的。
- 注意,如果給 serializeToString()傳入非 DOM 對象,就會導(dǎo)致拋出錯誤。
-
瀏覽器對 XPath 的支持
- XPath 是為了在 DOM 文檔中定位特定節(jié)點而創(chuàng)建的,因此它對 XML 處理很重要。在 DOM Level 3之前,XPath 相關(guān)的 API 沒有被標準化。DOM Level 3 開始著手標準化 XPath。很多瀏覽器實現(xiàn)了 DOM Level 3 XPath 標準,但 IE 決定按照自己的方式實現(xiàn)。
-
DOM Level 3 XPath
- DOM Level 3 XPath 規(guī)范定義了接口,用于在 DOM 中求值 XPath 表達式。要確定瀏覽器是否支持DOM Level 3 XPath,可以使用以下代碼:
let supportsXPath = document.implementation.hasFeature("XPath", "3.0");
- 雖然這個規(guī)范定義了不少類型,但其中最重要的兩個是 XPathEvaluator 和 XPathResult。XPathEvaluator 用于在特定上下文中求值 XPath 表達式,包含三個方法。
- createExpression(expression, nsresolver),用于根據(jù) XPath 表達式及相應(yīng)的命名空間計算得到一個 XPathExpression,XPathExpression 是查詢的編譯版本。這適合于同樣的查詢要運行多次的情況。
- createNSResolver(node),基于 node 的命名空間創(chuàng)建新的 XPathNSResolver 對象。當對使用名稱空間的 XML 文檔求值時,需要 XPathNSResolver 對象。
- evaluate(expression, context, nsresolver, type, result),根據(jù)給定的上下文和命名空間對 XPath 進行求值。其他參數(shù)表示如何返回結(jié)果。
- Document 類型通常是通過 XPathEvaluator 接口實現(xiàn)的,因此可以創(chuàng)建 XPathEvaluator 的實例,或使用 Document 實例上的方法(包括 XML 和 HTML 文檔)。
- 在上述三個方法中,使用最頻繁的是 evaluate()。這個方法接收五個參數(shù):XPath 表達式、上下文節(jié)點、命名空間解析器、返回的結(jié)果類型和 XPathResult 對象(用于填充結(jié)果,通常是 null,因為結(jié)果也可能是函數(shù)值)。第三個參數(shù),命名空間解析器,只在 XML 代碼使用 XML 命名空間的情況下有必要。如果沒有使用命名空間,這個參數(shù)也應(yīng)該是 null。第四個參數(shù)要返回值的類型是如下 10 個常量值之一。
- XPathResult.ANY_TYPE:返回適合 XPath 表達式的數(shù)據(jù)類型。
- XPathResult.NUMBER_TYPE:返回數(shù)值。
- XPathResult.STRING_TYPE:返回字符串值。
- XPathResult.BOOLEAN_TYPE:返回布爾值。
- XPathResult.UNORDERED_NODE_ITERATOR_TYPE:返回匹配節(jié)點的集合,但集合中節(jié)點的順序可能與它們在文檔中的順序不一致。
- XPathResult.ORDERED_NODE_ITERATOR_TYPE:返回匹配節(jié)點的集合,集合中節(jié)點的順序與它們在文檔中的順序一致。這是非常常用的結(jié)果類型。
- XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:返回節(jié)點集合的快照,在文檔外部捕獲節(jié)點,因此對文檔的進一步修改不會影響該節(jié)點集合。集合中節(jié)點的順序可能與它們在文檔中的順序不一致。
- XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:返回節(jié)點集合的快照,在文檔外部捕獲節(jié)點,因此對文檔的進一步修改不會影響這個節(jié)點集合。集合中節(jié)點的順序與它們在文檔中的順序一致。
- XPathResult.ANY_UNORDERED_NODE_TYPE:返回匹配節(jié)點的集合,但集合中節(jié)點的順序可能與它們在文檔中的順序不一致。
- XPathResult.FIRST_ORDERED_NODE_TYPE:返回只有一個節(jié)點的節(jié)點集合,包含文檔中第一個匹配的節(jié)點。
- 指定的結(jié)果類型決定了如何獲取結(jié)果的值。下面是一個典型的示例:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); if (result !== null) { let element = result.iterateNext(); while(element) { console.log(element.tagName); node = result.iterateNext(); } }
- 這個例子使用了 XPathResult.ORDERED_NODE_ITERATOR_TYPE 結(jié)果類型,也是最常用的類型。如果沒有節(jié)點匹配 XPath 表達式,evaluate()方法返回 null;否則,返回 XPathResult 對象。返回的 XPathResult 對象上有相應(yīng)的屬性和方法用于獲取特定類型的結(jié)果。如果結(jié)果是節(jié)點迭代器,無論有序還是無序,都必須使用 iterateNext()方法獲取結(jié)果中每個匹配的節(jié)點。在沒有更多匹配節(jié)點時,iterateNext()返回 null。
- 如果指定了快照結(jié)果類型(無論有序還是無序),都必須使用 snapshotItem()方法和 snapshotLength屬性獲取結(jié)果,如以下代碼所示:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (result !== null) { for (let i = 0, len=result.snapshotLength; i < len; i++) { console.log(result.snapshotItem(i).tagName); } }
- 這個例子中,snapshotLength 返回快照中節(jié)點的數(shù)量,而 snapshotItem()返回快照中給定位置的節(jié)點(類似于 NodeList 中的 length 和 item())。
- DOM Level 3 XPath 規(guī)范定義了接口,用于在 DOM 中求值 XPath 表達式。要確定瀏覽器是否支持DOM Level 3 XPath,可以使用以下代碼:
-
單個節(jié)點結(jié)果
- XPathResult.FIRST_ORDERED_NODE_TYPE 結(jié)果類型返回匹配的第一個節(jié)點,可以通過結(jié)果的singleNodeValue 屬性獲取。比如:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); if (result !== null) { console.log(result.singleNodeValue.tagName); }
- 與其他查詢一樣,如果沒有匹配的節(jié)點,evaluate()返回 null。如果有一個匹配的節(jié)點,則要使用 singleNodeValue 屬性取得該節(jié)點。這對 XPathResult.FIRST_ORDERED_NODE_TYPE 也一樣。
- XPathResult.FIRST_ORDERED_NODE_TYPE 結(jié)果類型返回匹配的第一個節(jié)點,可以通過結(jié)果的singleNodeValue 屬性獲取。比如:
-
簡單類型結(jié)果
- 使用布爾值、數(shù)值和字符串 XPathResult 類型,可以根據(jù) XPath 獲取簡單、非節(jié)點數(shù)據(jù)類型。這些結(jié)果類型返回的值需要分別使用 booleanValue、numberValue 和 stringValue 屬性獲取。對于布爾值類型,如果至少有一個節(jié)點匹配 XPath 表達式,booleanValue 就是 true;否則,booleanValue為 false。比如:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.BOOLEAN_TYPE, null); console.log(result.booleanValue);
- 在這個例子中,如果有任何節(jié)點匹配"employee/name",booleanValue 屬性就等于 true。
- 對于數(shù)值類型,XPath 表達式必須使用返回數(shù)值的 XPath 函數(shù),如 count()可以計算匹配給定模式的節(jié)點數(shù)。比如:
let result = xmldom.evaluate("count(employee/name)", xmldom.documentElement, null, XPathResult.NUMBER_TYPE, null); console.log(result.numberValue);
- 以上代碼會輸出匹配"employee/name"的節(jié)點數(shù)量(比如 2)。如果在這里沒有指定 XPath 函數(shù),numberValue 就等于 NaN。
- 對于字符串類型,evaluate()方法查找匹配 XPath 表達式的第一個節(jié)點,然后返回其第一個子節(jié)點的值,前提是第一個子節(jié)點是文本節(jié)點。如果不是,就返回空字符串。比如:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.STRING_TYPE, null); console.log(result.stringValue);
- 這個例子輸出了與"employee/name"匹配的第一個元素中第一個文本節(jié)點包含的文本字符串。
- 使用布爾值、數(shù)值和字符串 XPathResult 類型,可以根據(jù) XPath 獲取簡單、非節(jié)點數(shù)據(jù)類型。這些結(jié)果類型返回的值需要分別使用 booleanValue、numberValue 和 stringValue 屬性獲取。對于布爾值類型,如果至少有一個節(jié)點匹配 XPath 表達式,booleanValue 就是 true;否則,booleanValue為 false。比如:
-
默認類型結(jié)果
- 所有 XPath 表達式都會自動映射到特定類型的結(jié)果。設(shè)置特定結(jié)果類型會限制表達式的輸出。不過,可以使用 XPathResult.ANY_TYPE 類型讓求值自動返回默認類型結(jié)果。通常,默認類型結(jié)果是布爾值、數(shù)值、字符串或無序節(jié)點迭代器。要確定返回的結(jié)果類型,可以訪問求值結(jié)果的 resultType 屬性,如下例所示:
let result = xmldom.evaluate("employee/name", xmldom.documentElement, null, XPathResult.ANY_TYPE, null); if (result !== null) { switch(result.resultType) { case XPathResult.STRING_TYPE: // 處理字符串類型break; case XPathResult.NUMBER_TYPE: // 處理數(shù)值類型break; case XPathResult.BOOLEAN_TYPE: // 處理布爾值類型break; case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: // 處理無序節(jié)點迭代器類型break; default: // 處理其他可能的結(jié)果類型} }
- 使用 XPathResult.ANY_TYPE 可以讓使用 XPath 變得更自然,但在返回結(jié)果后則需要增加額外的判斷和處理。
- 所有 XPath 表達式都會自動映射到特定類型的結(jié)果。設(shè)置特定結(jié)果類型會限制表達式的輸出。不過,可以使用 XPathResult.ANY_TYPE 類型讓求值自動返回默認類型結(jié)果。通常,默認類型結(jié)果是布爾值、數(shù)值、字符串或無序節(jié)點迭代器。要確定返回的結(jié)果類型,可以訪問求值結(jié)果的 resultType 屬性,如下例所示:
-
命名空間支持
- 對于使用命名空間的 XML 文檔,必須告訴 XPathEvaluator 命名空間信息,才能進行正確求值。處理命名空間的方式有很多,看下面的示例 XML 代碼:
<?xml version="1.0" ?> <wrox:books xmlns:wrox="http://www.wrox.com/"> <wrox:book> <wrox:title>Professional JavaScript for Web Developers</wrox:title> <wrox:author>Nicholas C. Zakas</wrox:author></wrox:book> <wrox:book> <wrox:title>Professional Ajax</wrox:title> <wrox:author>Nicholas C. Zakas</wrox:author> <wrox:author>Jeremy McPeak</wrox:author> <wrox:author>Joe Fawcett</wrox:author> </wrox:book> </wrox:books>
- 在這個 XML 文檔中,所有元素的命名空間都屬于 http://www.wrox.com/,都以 wrox 前綴標識。如果想使用 XPath 查詢該文檔,就需要指定使用的命名空間,否則求值會失敗。
- 第一種處理命名空間的方式是通過 createNSResolver()方法創(chuàng)建 XPathNSResolver 對象。這個方法只接收一個參數(shù),即包含命名空間定義的文檔節(jié)點。對上面的例子而言,這個節(jié)點就是 document元素
<wrox:books>
,其 xmlns 屬性定義了命名空間。為此,可以將該節(jié)點傳給 createNSResolver(),然后得到的結(jié)果就可以在 evaluate()方法中使用:let nsresolver = xmldom.createNSResolver(xmldom.documentElement); let result = xmldom.evaluate("wrox:book/wrox:author", xmldom.documentElement, nsresolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); console.log(result.snapshotLength);
- 把 nsresolver 傳給 evaluate()之后,可以確保 XPath 表達式中使用的 wrox 前綴能夠被正確理解。假如不使用 XPathNSResolver,同樣的表達式就會導(dǎo)致錯誤。
- 第二種處理命名空間的方式是定義一個接收命名空間前綴并返回相應(yīng) URI 的函數(shù),如下所示:
let nsresolver = function(prefix) { switch(prefix) { case "wrox": return "http://www.wrox.com/"; // 其他前綴及返回值} }; let result = xmldom.evaluate("count(wrox:book/wrox:author)", xmldom.documentElement, nsresolver, XPathResult.NUMBER_TYPE, null); console.log(result.numberValue);
- 在并不知曉文檔的哪個節(jié)點包含命名空間定義時,可以采用這種定義命名空間解析函數(shù)的方式。只要知道前綴和 URI,就可以定義這樣一個函數(shù),然后把它作為第三個參數(shù)傳給 evaluate()。
- 對于使用命名空間的 XML 文檔,必須告訴 XPathEvaluator 命名空間信息,才能進行正確求值。處理命名空間的方式有很多,看下面的示例 XML 代碼:
-
瀏覽器對 XSLT 的支持
- 可擴展樣式表語言轉(zhuǎn)換(XSLT,Extensible Stylesheet Language Transformations)是與 XML 相伴的一種技術(shù),可以利用 XPath 將一種文檔表示轉(zhuǎn)換為另一種文檔表示。與 XML 和 XPath 不同,XSLT 沒有與之相關(guān)的正式 API,正式的 DOM 中也沒有涵蓋它。因此瀏覽器都以自己的方式實現(xiàn) XSLT。率先在JavaScript 中支持 XSLT 的是 IE。
-
XSLTProcessor 類型
- Mozilla 通過增加了一個新類型 XSLTProcessor,在 JavaScript 中實現(xiàn)了對 XSLT 的支持。通過使用 XSLTProcessor 類型,開發(fā)者可以使用 XSLT 轉(zhuǎn)換 XML 文檔,其方式類似于在 IE 中使用 XSL 處理器。自從 XSLTProcessor 首次實現(xiàn)以來,所有瀏覽器都照抄了其實現(xiàn),從而使 XSLTProcessor 成了通過 JavaScript 完成 XSLT 轉(zhuǎn)換的事實標準。
- 與 IE 的實現(xiàn)一樣,第一步是加載兩個 DOM 文檔:XML 文檔和 XSLT 文檔。然后,使用 importStyleSheet()方法創(chuàng)建一個新的 XSLTProcessor,將 XSLT 指定給它,如下所示:
let processor = new XSLTProcessor() processor.importStylesheet(xsltdom);
- 最后一步是執(zhí)行轉(zhuǎn)換,有兩種方式。如果想返回完整的 DOM文檔,就調(diào)用 transformToDocument();如果想得到文檔片段,則可以調(diào)用 transformToFragment()。一般來說,使用 transformToFragment()的唯一原因是想把結(jié)果添加到另一個 DOM 文檔。
- 如果使用 transformToDocument(),只要傳給它 XML DOM,就可以將結(jié)果當作另一個完全不同的 DOM 來使用。比如:
let result = processor.transformToDocument(xmldom); console.log(serializeXml(result));
- transformToFragment()方法接收兩個參數(shù):要轉(zhuǎn)換的 XML DOM 和最終會擁有結(jié)果片段的文檔。這可以確保新文本片段可以在目標文檔中使用。比如,可以把 document 作為第二個參數(shù),然后將創(chuàng)建的片段添加到其頁面元素中。比如:
let fragment = processor.transformToFragment(xmldom, document); let div = document.getElementById("divResult"); div.appendChild(fragment);
- 這里,處理器創(chuàng)建了由 document 對象所有的片段。這樣就可以將片段添加到當前頁面的
<div>
元素中了。 - 如果 XSLT 樣式表的輸出格式是"xml"或"html",則創(chuàng)建文檔或文檔片段理所當然。不過,如果輸出格式是"text",則通常意味著只想得到轉(zhuǎn)換后的文本結(jié)果。然而,沒有方法直接返回文本。在輸出格式為"text"時調(diào)用 transformToDocument()會返回完整的 XML 文檔,但這個文檔的內(nèi)容會因瀏覽器而異。比如,Safari 返回整個 HTML 文檔,而 Opera 和 Firefox 則返回只包含一個元素的文檔,其中輸出就是該元素的文本。
- 解決方案是調(diào)用 transformToFragment(),返回只有一個子節(jié)點、其中包含結(jié)果文本的文檔片段。之后,可以再使用以下代碼取得文本:
let fragment = processor.transformToFragment(xmldom, document); let text = fragment.firstChild.nodeValue; console.log(text);
- 這種方式在所有支持的瀏覽器中都可以正確返回轉(zhuǎn)換后的輸出文本。
-
使用參數(shù)
- XSLTProcessor 還允許使用 setParameter()方法設(shè)置 XSLT 參數(shù)。該方法接收三個參數(shù):命名空間 URI、參數(shù)本地名稱和要設(shè)置的值。通常,命名空間 URI 是 null,本地名稱就是參數(shù)名稱。setParameter()方法必須在調(diào)用 transformToDocument()或 transformToFragment()之前調(diào)用。例子如下:
let processor = new XSLTProcessor() processor.importStylesheet(xsltdom); processor.setParameter(null, "message", "Hello World!"); let result = processor.transformToDocument(xmldom);
- 與參數(shù)相關(guān)的還有兩個方法:getParameter()和 removeParameter()。它們分別用于取得參數(shù)的當前值和移除參數(shù)的值。它們都以一個命名空間 URI(同樣,一般是 null)和參數(shù)的本地名稱為參數(shù)。比如:
let processor = new XSLTProcessor() processor.importStylesheet(xsltdom); processor.setParameter(null, "message", "Hello World!"); console.log(processor.getParameter(null, "message")); // 輸出"Hello World!" processor.removeParameter(null, "message"); let result = processor.transformToDocument(xmldom);
- 這幾個方法并不常用,只是為了操作方便。
- XSLTProcessor 還允許使用 setParameter()方法設(shè)置 XSLT 參數(shù)。該方法接收三個參數(shù):命名空間 URI、參數(shù)本地名稱和要設(shè)置的值。通常,命名空間 URI 是 null,本地名稱就是參數(shù)名稱。setParameter()方法必須在調(diào)用 transformToDocument()或 transformToFragment()之前調(diào)用。例子如下:
-
重置處理器
- 每個 XSLTProcessor 實例都可以重用于多個轉(zhuǎn)換,只是要使用不同的 XSLT 樣式表。處理器的reset()方法可以刪除所有參數(shù)和樣式表。然后,可以使用 importStylesheet()方法加載不同的XSLT 樣表,如下所示:
let processor = new XSLTProcessor() processor.importStylesheet(xsltdom); // 執(zhí)行某些轉(zhuǎn)換 processor.reset(); processor.importStylesheet(xsltdom2); // 再執(zhí)行一些轉(zhuǎn)換
- 在使用多個樣式表執(zhí)行轉(zhuǎn)換時,重用一個 XSLTProcessor 可以節(jié)省內(nèi)存。
- 每個 XSLTProcessor 實例都可以重用于多個轉(zhuǎn)換,只是要使用不同的 XSLT 樣式表。處理器的reset()方法可以刪除所有參數(shù)和樣式表。然后,可以使用 importStylesheet()方法加載不同的XSLT 樣表,如下所示:
-
小結(jié)
- 瀏覽器對使用 JavaScript 處理 XML 實現(xiàn)及相關(guān)技術(shù)相當支持。然而,由于早期缺少規(guī)范,常用的功能出現(xiàn)了不同實現(xiàn)。DOM Level 2 提供了創(chuàng)建空 XML 文檔的 API,但不能解析和序列化。瀏覽器為解析和序列化 XML 實現(xiàn)了兩個新類型。
- DOMParser 類型是簡單的對象,可以將 XML 字符串解析為 DOM 文檔。
- XMLSerializer 類型執(zhí)行相反操作,將 DOM 文檔序列化為 XML 字符串。
- 基于所有主流瀏覽器的實現(xiàn),DOM Level 3 新增了針對 XPath API 的規(guī)范。該 API 可以讓 JavaScript針對 DOM 文檔執(zhí)行任何 XPath 查詢并得到不同數(shù)據(jù)類型的結(jié)果。
- 最后一個與 XML相關(guān)的技術(shù)是 XSLT,目前并沒有規(guī)范定義其 API。Firefox最早增加了 XSLTProcessor類型用于通過 JavaScript 處理轉(zhuǎn)換。
- 瀏覽器對使用 JavaScript 處理 XML 實現(xiàn)及相關(guān)技術(shù)相當支持。然而,由于早期缺少規(guī)范,常用的功能出現(xiàn)了不同實現(xiàn)。DOM Level 2 提供了創(chuàng)建空 XML 文檔的 API,但不能解析和序列化。瀏覽器為解析和序列化 XML 實現(xiàn)了兩個新類型。