【問】xml的標準形式是: <Root> <Name>John</Name> <Age>16</Age> </Root> 現在假如是一個字元串的形式—— <Root><Name>John</Name><Age>16</Age></Root> 請教如何對該字元串格式化,以便成為標準的xml文件格式? ...
【問】xml的標準形式是:
<Root>
<Name>John</Name>
<Age>16</Age>
</Root>
現在假如是一個字元串的形式——
<Root><Name>John</Name><Age>16</Age></Root>
請教如何對該字元串格式化,以便成為標準的xml文件格式?
【錯誤回答】
直接使用XmlDocument的LoadXml方法,然後輸出保存到一個新的xml文檔中。
【正解】
XmlDocument是存儲以及對xml文件操作的一個.NET基本類型。除了對xml進行增刪改查之外還可以直接對xml文件進行格式化操作。XmlDocument其中自帶一個方法“WriteTo”,該方法需要一個繼承TextWriter類的子類。針對xml文件,應該選用XmlTextWriter;XmlTextWriter又需要一個StringWriter流,而StringWriter需要一個Stream對象。恰巧StringBuilder是實現了Stream抽象類的子類。因此可以被使用。代碼如下:
[C#]
XmlDocument doc = new XmlDocument();
doc.LoadXml("<Root><Name>John</Name><Age>16</Age></Root>");
StringBuilder sub = new StringBuilder();
StringWriter sw = new StringWriter(sub);
XmlTextWriter xw = new XmlTextWriter(sw);
xw.Formatting = Formatting.Indented;
doc.WriteTo(xw);
Console.WriteLine(sub);
[VB.NET]
Dim doc As New XmlDocument()
doc.LoadXml("<Root><Name>John</Name><Age>16</Age></Root>")
Dim [sub] As New StringBuilder()
Dim sw As New StringWriter([sub])
Dim xw As New XmlTextWriter(sw)
xw.Formatting = Formatting.Indented
doc.WriteTo(xw)
Console.WriteLine([sub])
值得註意的是:您必須設置XmlTextWriter的Formatting格式為Indented(鋸齒,自動縮進的意思),否則仍然無法實現效果。
【總結】
1)首先聲明一個StringBuilder對象,作為目標源。
2)其次聲明一個StringWriter,作為連接該對象的“管道”(字元串“寫入流”)。
3)然後聲明一個XmlTextWriter,連接StringWriter(把StringWriter作為參數傳入),並設置Formatting格式為Indented。
4)最後通過XmlDocument的WriteTo方法連接到XmlTextWriter即可。
【拓展】
關於“Stream”,“Reader/Writer”的“IO”探討
眾所周知,System.IO命名空間裡邊包括了大量支持文件、記憶體、網路、字元串等流寫入(出)的類以及旗下方法。其主要從幾個抽象類派生而成:
1)Stream:該類主要用作目標對象。一般地,微軟這方面命名是:“目標對象”+Stream——
文件流:FileStream。
記憶體流:MemoryStream。
網路流:NetWorkStream(值得註意的是有一個類是位於System.NET.Sockets,專門用Socket或者TCP/IP等通訊發送信息時用)。
2) TextWriter:該類用於執行“寫”操作,寫入到指定某個繼承Stream類的子類。這方面微軟有對應的類:
文件、記憶體、網路流寫入:StreamWriter。
字元串流寫入:StringWriter(註意:其需要一個StringBuilder,而不是需要一個Stream子類對象作為參數)。
Xml文件流寫入:XmlWriter和XmlTextWriter,前者自身是一個抽象類(不是繼承TextWriter),單獨也可以使用(使用Create方法,支持Stream和StringBuilder等),簡單實現一些非常簡單基本的xml讀寫操作(主要針對字元串格式的),後者繼承了XmlWriter(構造函數參數支持對Stream和TextWriter子類進行寫入),實現了其中所有的abstract方法,能夠讀寫複雜的數據類型,如CData等)。同時還支持Formatting格式化,就像上面的例子。
不過有意思的在於:凡是以上類(以Writer結尾的),要寫入到目標中的話必須顯式調用Close或者Flush方法,否則這是駐留在記憶體中,不會真正寫入到目標的。這也就是為什麼很多時候程式沒有錯誤,目標總是得不到的原因。
3) TextReader:該類用於執行“讀”操作,讀入到指定某個繼承Stream類的子類。這方面微軟有對應的類:
文件、記憶體、網路流讀入:StreamReader。
字元串流讀入:StringReader(註意:其需要一個string對象,而不是需要一個Stream子類對象作為參數)。
Xml文件流讀入:XmlReader和XmlTextReader,前者自身是一個抽象類(不是繼承TextReader),單獨也可以使用(使用Create方法,支持TextReader和Stream等),簡單實現一些非常簡單基本的xml讀寫操作(主要針對字元串格式的),後者繼承了XmlWriter,實現了其中所有的abstract方法,能夠讀寫複雜的數據類型等)。