1. 程式人生 > >JaveScript 中使用 XSLT轉換XML文檔

JaveScript 中使用 XSLT轉換XML文檔

選擇符 child 形式 size app nsf ria value 方式

我們經常將數據存儲在XML 中,在展示的時候需要轉換為其它的形式,這裏介紹使用XSLT 對XML數據進行轉換。

要學習XSLT對XML的轉換,需要先了解三個文件。

第一個是存儲數據的XML文件:employees.xml

<?xml version="1.0"?>
<employees>
    <employee title="Software Engineer">
        <name>Nicholas C. Zakas</name>
    </employee>
    <employee title="Salesperson"
> <name>Jim Smith</name> </employee> </employees>

第二個是存儲XSLT的文件:employees.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" />
    
    <xsl:template match="/">
<ul> <xsl:apply-templates select="*" /> </ul> </xsl:template> <xsl:template match="employee"> <li><xsl:value-of select="name" />, <em><xsl:value-of select="@title" /></em></li> </xsl:template>
</xsl:stylesheet>

第三個是我們進行轉換的代碼example.htm:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <title>XSLTProcessor Example</title>   
 5 
 6     <script type="text/javascript">
 7         window.onload = function () {
 8         
 9             //use XHR to load
10             var xmlhttp = new XMLHttpRequest();
11             xmlhttp.open("get", "employees.xml", false);
12             xmlhttp.send(null);
13             var xmldom = xmlhttp.responseXML;
14             
15             xmlhttp = new XMLHttpRequest();
16             xmlhttp.open("get", "employees.xslt", false);
17             xmlhttp.send(null);
18             var xsltdom = xmlhttp.responseXML;  
19 
20             var processor = new XSLTProcessor();
21             processor.importStylesheet(xsltdom);
22 
23             var result = processor.transformToDocument(xmldom);
24             var div = document.getElementById("divResult");
25             
26             var xml = (new XMLSerializer()).serializeToString(result);
27             alert(xml);
28             div.innerHTML = xml;
29 
30         }
31     </script>           
32 </head>
33 <body>
34     <p>This example loads employees.xml and transforms it using employees.xslt. 
35     The resulting code is then displayed.</p>
36     <div id="divResult"></div>
37 </body>
38 </html>

在這裏我們通過 XSLTProcessor 類型使用XSLT轉換XML文檔,第一步加載兩個DOM文檔,一個基於XML,另一個基於XSLT,下面的代碼在Edge 中可以順利執行,在Chrome中,因為禁止從本地裝載文件隨意會會失敗,如果從網絡服務器上讀取數據則沒有問題。

//use XHR to load
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", "employees.xml", false);
xmlhttp.send(null);
var xmldom = xmlhttp.responseXML;
            
xmlhttp = new XMLHttpRequest();
xmlhttp.open("get", "employees.xslt", false);
xmlhttp.send(null);
var xsltdom = xmlhttp.responseXML;  

然後創建一個新XSLTProcessor對象,並使用importStylesheet()方法為其指定一個XSLT

var processor = new XSLTProcessor();
processor.importStylesheet(xsltdom);

最後一步是執行轉換,這一步有兩種不同的方式,如果想返回一個完整的DOM文檔,可以調用transformToDocument().而通過調用transforToFragment()則可以得到一個文檔片段對象。一般來說。使用transformToFragment()的唯一理由,就是你想把返回的結果添加到另一個DOM文檔中。

在使用transforToDocument()時,只要傳入XML DOM,就可以將結果作為一個完全不同的DOM文檔來使用。來看例子

var result = processor.transformToDocument(xmldom);

我們將result 結果進行序列化

var xml = (new XMLSerializer()).serializeToString(result);

來看轉換後的結果

<ul>
<li>Nicholas C. Zakas, <em>Software Engineer</em></li>
<li>Jim Smith, <em>Salesperson</em></li>
</ul>

下面我們來看一下XSLT中的定義:

下面的這段代碼會讓我們將所有的內容都放到<ul></ul>之中,之所以會這樣是因為我們的選擇符指定了全部 select="*"

<xsl:template match="/">
       <ul>
           <xsl:apply-templates select="*" />
       </ul>
</xsl:template>

下面這段代碼的含義是對 employee 元素進行轉換 match="employee"

將name 元素放到<li></li>中 select="name"

將title 屬性提取出來放到<em></em>中 select="@title"

 <xsl:template match="employee">
        <li><xsl:value-of select="name" />, <em><xsl:value-of select="@title" /></em></li>
</xsl:template>

而transformToFragment()方法接收兩個參數:要轉換的XML DOM 和應該擁有結果片段的文檔。換句話說,如果你想將返回的片段插入到頁面中,只要將document作為第二個參數即可。

我們只需要將example.htm中 23 - 28 行代碼替換成下面代碼就可以了。

var fragment = processor.transformToFragment(xmldom, document);
var div = document.getElementById("divResult");
            
div.appendChild(fragment);

這裏,處理器創建了一個有document對象擁有的片段。這樣,就可以將返回的片段添加到頁面中已有的<div>元素中了。

在XSLT樣式表的輸出格式為"xml","html"的情況下,創建文檔或文檔片段會非常有用。

1.使用參數

XSLTProcessor 也支持使用 setParameter()來設置XSLT的參數,這個方法接收三個參數:命名空間URI,參數的內部名稱和要設置的值。通常,命名空間URI都是null,而內部名稱就是參數的名稱。另外必須在調用transformToDocument()或transformToFragment()之前調用這個方法。來看例子

我們先看XSLT文件 employees2.xslt:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" />

    <xsl:param name="message" />
        
    <xsl:template match="/">
       <ul>
           <xsl:apply-templates select="*" />
       </ul>
       <p>Message: <xsl:value-of select="$message" /></p>
    </xsl:template>

    <xsl:template match="employee">
        <li><xsl:value-of select="name" />, <em><xsl:value-of select="@title" /></em></li>
    </xsl:template>

</xsl:stylesheet>

針對 example.htm的修改

第16行替換為

xmlhttp.open("get", "employees2.xslt", false);

第23 - 28替換為下面代碼

processor.setParameter(null, "message", "Hello World!");

var fragment = processor.transformToFragment(xmldom, document);
var div = document.getElementById("divResult");
            
div.appendChild(fragment);            

我們看運行後的結果:通過轉換將模板中的 $message變量替換成了我們傳入的參數"Hello World!"

<div id="divResult"><ul>
<li>Nicholas C. Zakas, <em>Software Engineer</em></li>
<li>Jim Smith, <em>Salesperson</em></li>
</ul>
<p>Message: Hello World!</p>
</div>

還有兩個與參數有關的方法,getParamenter()和removeParamenter(),分別用於取得和一處當前參數的值。這兩個方法都要接受命名空間參數和參數內部i名稱。例如

var processor = new XSLTProcessor();
processor.importStylesheet(xsltdom);
processor.setParameter(null, "message", "Hello World!");

alert(processor.getParaeter(null,"message")); //輸出 “Hello World!"
processor.removeParameter(null,"message");
var fragment = processor.transformToFragment(xmldom, document);

這兩個方法並不常用。

2.重置處理器

每個XSLTProcessor 的實例都可以重用,以便使用不同的XSLT樣式表執行不同的轉換。重置處理器時要調用reset()方法,這個方法會從處理器中移除所有的參數和樣式表。然後,你就可以再次調用importStylesheet(),以加載不同的XSLT樣式表,如下面的例子

var processor = new XSLTProcessor();
processor.importStylesheet(xsltdom);

//執行轉換

processor.reset();
processor.importStylesheet(xsltdom2);

//在執行轉換

在需要基於多個樣式表進行轉換時,重用一個XSLTProcessor可以節省內存。

JaveScript 中使用 XSLT轉換XML文檔