1. 程式人生 > >XDocument 獲取包括第一行的宣告(版本、編碼)的所有節點

XDocument 獲取包括第一行的宣告(版本、編碼)的所有節點

XDocument儲存為xml檔案的方法如下:
XDocument doc = new XDocument(
    new XDeclaration("1.0","UTF-8",null),
    new XElement("Persons",                         
        new XElement("Person",
            new XAttribute("id","1"),
            new XElement("Name","張三"),
            new XElement("Age",18)
        )                  
    )
    );
doc.Save("person.xml");

person.xml開啟時有第一行的版本和編碼宣告:

<?xml version="1.0" encoding="utf-8"?>

<Persons>
  <Person id="1">
    <Name>張三</Name>
    <Age>18</Age>
  </Person>
</Persons>


但是有時不想儲存為檔案,直接獲取上面內容為儲存在一個string中:
string xml = doc.ToString();

此時xml的值為下面,獲取不到xml第一行的宣告:
<Persons>
  <Person id="1">
    <Name>張三</Name>
    <Age>18</Age>
  </Person>
</Persons>



解決方法有幾種:

第1種,比較簡單:
string xml = doc.Declaration.ToString() + doc.ToString();

第2種,寫個擴充套件方法

 public static string ToStringWithDeclaration(this XDocument doc, SaveOptions options = SaveOptions.DisableFormatting)
        {
            return doc.Declaration.ToString() + doc.ToString(options);
        }
呼叫:
string xml = doc.ToStringWithDeclaration();

第3種,同樣寫個擴充套件方法封裝起來

public static string ToStringWithDeclaration(this XDocument doc)
       {
           StringBuilder sb = new StringBuilder();
           using (TextWriter tw = new StringWriter(sb))
           {               
               doc.Save(tw, SaveOptions.DisableFormatting);
           }         
           return sb.ToString();
       }

這種方法有個問題是生成的編碼宣告變成了encoding="utf-16",要想換成encoding="utf-8"可
寫個類Utf8StringWriter繼承StringWriter,並設定過載屬性Encoding為UTF8,完整程式碼如下
 public class Utf8StringWriter : StringWriter
        {
            public Utf8StringWriter(StringBuilder sb) : base(sb){ }
            public override Encoding Encoding { get { return Encoding.UTF8; } }
        }
       public static string ToStringWithDeclaration(this XDocument xdoc)
       {
           StringBuilder sb = new StringBuilder();
           using (TextWriter tw = new Utf8StringWriter(sb))
           {   
               xdoc.Save(tw, SaveOptions.DisableFormatting);
           }
           return sb.ToString();
       }


備註:

XDocument.ToString 方法有2個過載列表,可以設定XML節點是否縮排

名稱                                      說明
ToString()                            返回此節點的縮排 XML。
ToString(SaveOptions)     返回此節點的 XML,還可以選擇禁用格式設定。


SaveOptions有兩個列舉值:
   DisableFormatting 不縮排
   None                         縮排

XDocument.Save 方法也有個引數SaveOptions可以設定。