.Net框架下的XSLT轉換技術簡介
2024-07-10 12:59:02
供稿:網友
一.前言:
xslt轉換技術是xml中的一項重要技術,本文將向xml開發者介紹.net框架下的一些不同的xslt轉換技術。同時,本文還將介紹如何運用各種不同的輸入數據源以完成一個xslt轉換。在.net框架下,system.xml.xsl.xsltransform類能根據一個xslt樣式表文件轉換一個xml文檔,它是xslt轉換中最重要的一個類,同時它能夠支持w3c的xslt 1.0的語法,其運用的命名空間是http://www.w3.org/1999/xsl/transform。
二.與xslt轉換相關的輸入數據源:
.net框架下有許多類可以完成讀取xml文檔以實現xslt轉換的功能,其中最有用的當屬system.xml.xmlreader類了。它是一個虛基類,因此不能被直接運用,必須有一個類繼承它。.net框架下有三個類是從該類繼承過來的:xmltextreader類、xmlnodereader類以及xmlvalidatingreader類,它們都是包含在命名空間system.xml中的。其中xmltextreader類能從一個xml文檔中讀取字符流并檢查該文檔是否是具有良好結構(well-formed)的,但它并不運用dtd或是xml模式進行xml文檔的驗證工作。xmlnodereader類允許數據從任何xml文檔對象模型(dom)的api中被讀取,比如一個system.xml.xmlnode對象,而且xmlnode對象并不必是一個完整的xml文檔的根節點,它可以是其一個子節點。xmlvalidatingreader類能保證一個xml文檔是遵從一個dtd或是xml模式所確定的規則的。下面是一個xmlreader類作為xslt轉換的輸入數據源的應用實例。
// 將一個xslt文件的字符串導入到一個textreader對象中
system.io.textreader tr = new system.io.streamreader("numbers.xsl");
// 將上面的textreader對象作為xmltextreader對象的數據源
system.xml.xmlreader xr = new system.xml.xmltextreader(tr);
// 創建一個新的xsltransform對象
system.xml.xsl.xsltransform trans = new system.xml.xsl.xsltransform();
// 將xmlreader對象中的樣式表導入到上面的xsltransform對象中
trans.load(xr);
另一種能完成讀取xml文檔以實現xslt轉換功能的類是system.xml.xpath.xpathnavigator類或是任何實現了system.xml.xpath.ixpathnavigable接口的類,這些類包括了system.xml.xpath.xpathdocument類,system.xml.xmldocument類以及system.xml.xmldatadocument類。system.xml.xpath.xpathnavigator類是基于xpath數據模型的,并提供了能夠對任何xml數據進行xpath查詢的方法。
system.xml.xpath.xpathdocument類是這些類中速度最快的一個類,因為它是只讀的,在xslt轉換對速度的要求很高時應該使用這個類。system.xml.xmldocument類的效率僅次于system.xml.xpath.xpathdocument類,而system.xml.xmldatadocumnet類并不適合xslt轉換,因為它的效率最低。system.xml.xpath.ixpathnavigable接口可以在任何數據源上實現,同時它允許任何類型的數據作為xslt轉換的數據源。下面的示例代碼可以被接在上面的例子后面。
// 創建一個新的xpathdocument對象,并從一個xml文件導入數據源
system.xml.xpath.xpathdocument xp = new
system.xml.xpath.xpathdocument("numbers.xml");
// 創建一個新的xpathnavigator對象
system.xml.xpath.xpathnavigator xpn = xp.createnavigator();
xsltransform類要求xml或xslt的數據源是一個xmlreader對象或是一個xpathnavigator對象。它的兩個最重要的方法是load()方法和transform()方法,這兩個方法并不提供重載的對stream對象直接進行處理的方法,但是卻可以間接地將stream對象作為xslt轉換的數據源,而該stream對象則是從xml文件或xslt樣式表中獲取的。下面的代碼創建了一個stream對象,并顯示了如何將它作為xslt轉換的數據源,不過該代碼段僅僅是一個示例,并沒有實際的數據存在。
// 創建一個新的stream對象
system.io.stream st = new system.io.memorystream();
// 在此運用一個xml文件填充上面的stream對象并將stream對象的位置置為0
st.position = 0;
// 將stream對象導入到一個xpathdocument對象中
system.xml.xpath.xpathdocument xp = new system.xml.xpath.xpathdocument(st);
// 對xslt文檔進行同樣的操作
system.io.stream xsltstream = new system.io.memorystream();
// 在此運用一個xslt文件填充上面的stream對象并將stream對象的位置置為0
st.position = 0;
// 創建一個xmlreader對象,并將上面的stream對象作為數據源
system.xml.xmlreader xsltxr = new system.xml.xmltextreader(xsltstream);
// 以后,該xmlreader對象就可以被傳遞到xsltransform類的load()方法中去了
上面的代碼中并沒有實際的數據存在,我們需要將xml文件或xslt樣式表填充到stream對象中才能進行實際的操作。另一種設置輸入數據源的方法是以字符串的形式從一個url獲取xml文檔或xslt文檔,同時還可能有一個可選擇的system.xml.xmlresolver對象,該方法是最直接也是最有效的方法。
三.與xslt轉換相關的輸出數據源:
在介紹了xslt轉換的輸入數據源之后,本文接著向大家介紹與之相關的輸出數據源。根據所運用的不同類型的輸出類,xsl:output元素有時可以被忽略掉。比如在運用xmlwriter類或xmlreader類作為輸出類的時候,該元素就被忽略掉了。有關xsl:output元素的詳細內容請參考msdn的文章"outputs from an xsltransform",這里限于篇幅就不多作介紹了。
綜上所述,進行xslt轉換的必要條件包括了一個xml文檔,一個xslt文檔以及一個能處理輸出的有效對象。下面的代碼運用了一個xpathdocument對象以及一個樣式表文件進行xslt轉換,其輸出的結果被直接顯示在控制臺中了。
// 創建一個新的xsltransform對象
system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();
// 從xsl文件中導入樣式表
xslt.load("numbers.xsl");
// 創建一個新的xpathdocument對象,并導入一個xml文件
system.xml.xpath.xpathdocument doc = new
system.xml.xpath.xpathdocument("numbers.xml");
// 創建一個新的xmltextwriter對象用于完成到控制臺的數據輸出
system.xml.xmltextwriter writer = new
system.xml.xmltextwriter(system.console.out);
// 進行實際的xslt轉換操作
xslt.transform(doc, null, writer);
// 在完成操作后關閉xmltextwriter對象
// 同時請注意一旦關閉該對象就不能往控制臺中寫任何額外信息了
writer.close();
四.與xslt轉換相關的流對象:
.net框架允許程序員將xslt轉換的結果直接輸出到一個system.io.stream對象,下面的代碼將使用一個用于輸出的system.io.memorystream對象,然后顯示如何運用它進行與xslt轉換的輸出相關的操作。
// 創建一個新的xsltransform對象
system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();
// 從xslt文件中導入樣式表
xslt.load("numbers.xsl");
// 導入一個xml文件
system.xml.xpath.xpathdocument doc = new
system.xml.xpath.xpathdocument("numbers.xml");
// 創建用于輸出的stream對象
system.io.stream str = new system.io.memorystream();
// 進行實際的轉換操作
xslt.transform(doc, null, str);
// 對stream對象進行flush操作,并將其位置置為0
str.flush();
str.position = 0;
如果一個system.xml.xmldocument對象或一個system.xml.xpath.xpathdocument對象已經被載入到主存中了,那么它們也可以被用作xslt轉換的輸入數據源。因為這兩個對象都實現了system.xml.xpath.ixpathnavigable接口,所以都可以作為xsltransform對象的transform()方法的參數被直接使用。
// 創建一個新的xsltransform對象
system.xml.xsl.xsltransform xslt = new system.xml.xsl.xsltransform();
// 從xslt文件中導入樣式表
xslt.load("numbersxml.xsl");
// 將一個xml文檔導入到一個xpathdocument對象中
system.xml.xpath.xpathdocument doc = new
system.xml.xpath.xpathdocument("numbers.xml");
// 創建用于輸出的stream對象
system.io.stream str = new system.io.memorystream();
system.xml.xmlwriter xw = new
system.xml.xmltextwriter(str,system.text.encoding.utf8);
// 進行實際的轉換操作
xslt.transform(doc, null, xw);
// 對xmlwriter對象進行flush操作,并將stream對象的位置置為0
xw.flush();
str.position = 0;
五.與xslt轉換相關的嵌入式腳本以及代碼:
.net框架中的xslt轉換對象提供了對在xslt文檔中用腳本擴展元素來嵌入腳本語言的支持。腳本語言所提供的一組功能比純xslt所提供的功能要豐富,經常可以用來對文檔內容進行更為復雜的操作,比如對其應用科學計算函數、訪問外部信息源等。在.net框架下,程序員運用msxsl:script元素可以標記xslt樣式表中的嵌入式腳本或代碼。腳本擴展元素必須在urn:schemas-microsoft-com:xslt namespace命名空間中聲明。.net框架中的分析器能夠支持c#、vb.net、vbscript或jscript等代碼編寫的腳本。在腳本元素中,我們通過提供一個implements-prefix屬性定義了函數所調用的命名空間,通過提供一個language屬性定義了函數所使用的編程語言。同時,我們得注意一個樣式表中可以嵌入多種語言的腳本代碼,但是同一個命名空間下只能使用同一種語言。下面的實例顯示了一個包含嵌入式c#函數的樣式表。
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/xsl/transform'
xmlns:msxsl='urn:schemas-microsoft-com:xslt'
xmlns:thescript='urn:customscript'>
<xsl:output omit-xml-declaration='yes' method='text'
media-type='text/plain' indent='no' />
<xsl:variable name='displayme' />
<msxsl:script implements-prefix='thescript' language='c#'>
<![cdata[
public string helloname(string name)
{
return "hello " + name;
}
]]>
</msxsl:script>
<xsl:template match='/'>
<xsl:text disable-output-escaping='yes'>print integers > 3</xsl:text>
<xsl:apply-templates select='root/numbers' />
script result: <xsl:value-of select='thescript:helloname("joe")' />
done: <xsl:value-of select='$displayme' />
</xsl:template>
<xsl:template match='numbers'>
numbers:<xsl:apply-templates select='integer[@value > 3]' />
</xsl:template>
<xsl:template match='integer'>
integer: <xsl:value-of select='@value' />
</xsl:template>
</xsl:stylesheet>
六.樣式表參數以及擴展對象:
xslt提供了一個在樣式表中使用參數以及擴展對象的機制。在.net框架下,程序員可以通過運用system.xml.xsl.xsltargumentlist類實現將參數或擴展對象傳遞到一個樣式表。在樣式表中使用參數的機制允許程序員聲明一個全局變量,該變量被定義為xsl:variable類型的元素,它是作為一個xsl:stylesheet的子元素而存在的,但它并不包含在xsl:template之中。通過調用xsltargumentlist類的addparam()方法程序員可以實現添加參數的功能,該方法中的三個參數依次為有效的名稱、命名空間的uri以及參數值。如果參數值不是一個字符串、布爾值、數字、節點片斷(node fragment)或節點集合(node set),那么它將被強制轉化為雙精度浮點值或是字符串。而一個擴展對象是任何一個能返回xslt數據類型值的.net類。通過調用xsltargumentlist類的addextensionobject()方法程序員可以實現添加擴展對象的功能,該方法中的兩個參數分別為有效的名稱以及命名空間的uri。下面的代碼顯示了如何運用xsltargumentlist類在樣式表中使用參數以及擴展對象的方法。
// 創建一個新的xpathdocument對象,并導入一個xml文件
system.xml.xpath.xpathdocument xp = new
system.xml.xpath.xpathdocument("numbers.xml");
// 創建一個新的xsltransform對象
system.xml.xsl.xsltransform trans = new system.xml.xsl.xsltransform();
// 導入一個xslt文件到上面的xsltransform對象中
trans.load("numbersextension.xsl");
// 創建一個新的xsltargumentlist對象
system.xml.xsl.xsltargumentlist xslarg = new
system.xml.xsl.xsltargumentlist();
// 調用xsltargumentlist對象的addparam()方法以添加參數
xslarg.addparam("displayme","","is this fun?");
// 創建一個新的擴展對象
sayhello hi = new sayhello();
// 調用xsltargumentlist對象的addextensionobject()方法以添加擴展對象
xslarg.addextensionobject("urn:sayhello",hi);
// 創建一個新的system.io.stream對象以處理輸出結果
system.io.stream str = new system.io.memorystream();
// 進行實際的轉換操作
trans.transform(xp, xslarg, str);
// 對stream對象進行flush操作,并將其位置置為0
str.flush();
str.position = 0;
// 創建一個新的streamreader對象以讀取流并返回字符串
system.io.streamreader sr = new system.io.streamreader(str);
string xmlout = sr.readtoend();
// 關閉streamreader 對象
sr.close();
// 將結果寫到控制臺中
console.write(xmlout);
// 擴展對象返回hello name
public class sayhello
{
public string helloname(string name) {
return "hello " + name;
}
}
通過上面的介紹,我們發現使用擴展對象和使用嵌入式腳本具有許多相同之處。下面我們分析一下使用擴展對象相對于使用嵌入式腳本的一些優缺點。
移植性:嵌入式腳本比擴展對象更容易移植,因為任何.net平臺都可以正確地用嵌入式腳本來轉換一個樣式表。而另一方面,使用擴展對象的樣式表則只能用一段代碼來進行轉換,而且需在.net平臺或其他一些支持擴展對象的平臺下進行,并要求這段代碼能正確地實現一個帶有效的名稱和命名空間uri的擴展對象。
大小:一個依賴于擴展對象的樣式表比包含嵌入式腳本的樣式表要小,而且更容易維護。
靈活性:正如我們看到的那樣,依賴于擴展對象的樣式表可以按照修改約束它們的擴展對象的功能來修改它們的行為。而使用嵌入式腳本的樣式表則永遠只能按照嵌入的腳本語言指定的功能執行操作。
性能:因為擴展對象是預編譯的,而不是即時編譯的,因此使用擴展對象的腳本的性能在某種程度上要比嵌入式腳本高一些。不過具體情況下還要考慮裝入樣式表的頻率以及嵌入式腳本的規模等因素。
可維護性:使用擴展對象的樣式表在修改和糾錯時可能比較困難,因為真正的代碼從樣式表和提供擴展對象實現的代碼中分離出去了。而嵌入式腳本盡管稍微慢一些,卻具有將所有代碼都置于本地的優點。
通過考慮上述一些因素,我們可以決定在具體的情況下是使用擴展對象還是使用嵌入式腳本了。
七.總結:
本文向大家介紹了.net框架下和xslt轉換相關的一些知識,xslt轉換技術是xml中的一項重要技術。.net框架對xslt轉換提供了穩健的支持,它不僅完全支持w3c定義的xslt規范,還有許多有用的擴展,比如在樣式表中嵌入多種語言的腳本、使用擴展對象來擴展xslt的功能等等,從而增強了.net應用程序中樣式表的易用性。最后,我希望大家能通過本文掌握.net框架有關xslt轉換的一些基本技術,并了解每種技術的優缺點以更好地應用于實際的項目。菜鳥學堂: