更多內容請查看:BizTalk動手實驗系列目錄
BizTalk 開發系列
最近在做一個BizTalk項目,對XML檔案的處理很複雜。本來是想找有沒有方法可以一次性去除XML檔案中節點和屬性的值的空格。但是找了很久沒有看到相關的方法。如果有知道該方法的麻煩跟我講一下:cbcye@live.com 不過下面我整理了一下與之相關的XML空白字元(WhiteSpace)。
先來看看這個問題比較一下這兩個XML是否一樣?
XML(一)
<AddBook>
<Name/>
<Mobile/>
</AddBook>
XML(二)
<AddBook><Name/><Mobile/></AddBook>
如果你覺得一樣的話,那麼我們來進行如下。我們使用的是XSLT(XML轉換語言)讀取整個XML文檔。此XSLT檔案的作用是拷貝整個源XML文檔中的節點到目標XML檔案中。
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
測試時在Visual Studio的XSLT調試介面設定斷點。在監看式視窗使用Xpath函數:node()來查看XML文檔中的節點變化情況。
XML(一)的節點:
XML(二)的節點:
從以上的測試資料可以看出當XML處於不同行的時候XML會多一些類型為whitespace的節點。由此可見XML(一)與XML(二)是不相同的。那為什麼它們之間不相同呢?那為什麼我們使用IE之類的XML解析器開啟兩個檔案的話看到的效果是一樣的?當然我們這裡不討論IE之類的是如何處理的(事實上是我也不知道IE是如何處理的:)。我們主要來看看這兩個XML之間為什麼不一樣。也就是本文要涉及的Whitespace。
首先我們來瞭解一下在XML裡什麼叫WiteSpace。XML 將以下四種字元歸為空白字元:斷行符號符(\r 或 ch(13))、分行符號(\n 或 ch(10))、定位字元 (\t) 以及空格 (' ')。在 XML 文檔中,空白字元分為兩類:
有意義空白字元 是文檔內容的一部分,應予以保留。
無意義空白字元 在編輯 XML 文檔時使用,以增加可讀性。這些空白字元一般在文檔交付時不予保留。
由此可見XML文檔有時根據處理需要會增加一些斷行符號、換行之類的特殊字元。但是如果這些字元在處理XML時不先清除(如果有必要的話)。那麼就會造成一些錯誤。比如在XSLT檔案中有如下運算式的話那麼XML檔案中的空白字元就有可能引用轉換處理錯誤。因為空白字元是不能作為節點名稱的。
<xsl:element name="{local-name()}">
瞭解了XML檔案中有無空白字元的區別與XML檔案中空白字元的用處之後我們來瞭解一下XML處理器是如果處理空白字元的。該如何根據需要處理空白字元。
XML 分析:XML 規範提供了一個內建屬性 xml:space 來告知 XML 分析器其是否應忽略空白字元。該屬性由其根項目的子項目來繼承。聲明時,必須將其指定為枚舉類型,其可能的值只能是“default”和“preserve”。如果指定為“preserve”,則所定義元素內的空白字元必須保留。
樣本:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns="http://quicklearn.cn"/>
<part1>
<ns0:books xmlns:ns0="http://books.quicklearn.cn"/>
<ns0:book>
<name>BizTalk Develop</name>
<ISDN>0101010101010</ISDN>
</ns0:book>
</ns0:books>
</part1>
<part2>
<ns1:customers xmlns:ns1="customers.quicklearn.cn">
<customer xml:space="preserve">
<name>Zhang San</name>
<mobile>133333333333</mobile>
<address>
<province>Guang Dong</province>
<city>Shen Zhen </city>
</address>
</customer>
</ns1:customers>
</part2>
</root>
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = false;
xmlDoc.Load(@"D:\Projects\Temp\XSLTTest\XSLTTest\XSLTTest\XMLData2.xml");
this.richTextBox1.Text = xmlDoc.OuterXml;
<?xml version="1.0" encoding="utf-8"?><root xmlns="http://quicklearn.cn"/><part1><ns0:books xmlns:ns0="http://books.quicklearn.cn"/><ns0:book><name>BizTalk Develop</name><ISDN>0101010101010</ISDN></ns0:book></ns0:books></part1><part2><ns1:customers xmlns:ns1="customers.quicklearn.cn"><customer xml:space="preserve">
<name>Zhang San</name>
<mobile>133333333333</mobile>
<address>
<province>Guang Dong</province>
<city>Shen Zhen </city>
</address>
</customer></ns1:customers></part2></root>
XSLT 轉換。W3C XSLT 規範提供了兩個元素(即 xsl:strip-space 和 xsl:preserve-spacea€”)來處理空白字元。xsl:strip-space 指定了應刪除空白字元文本節點(即文本節點完全由空白字元組成)的 XML 元素。請注意,xsl:strip-space 只有影響純空白字元的節點。xsl:strip-space 可以列為一組由空白字元或使用萬用字元(例如 *)隔開的元素。xsl:preserve-space 具有類似的文法,但執行的結果卻與 xsl:strip-space 正好相反。
使用方法:在XSLT檔案聲明全域屬性 <xsl:strip-space elements="*"/>或 <xsl:strip-space elements="element1 element2…"/>
輸出的效果與XML分析器相同。
總結
瞭解了XML空白字元的作用及XML分析與處理器處理方式。那麼在處理XML空白字元字元的時候,如果XML是給後台應用程式處理的話在處理之前最好先去除XML空白字元。如果XML是給使用者閱讀的話則保留相關的空白字元。