Linq to XML 的寫作非常方便。以往要組一個 xml ,都必須從 XmlDocument 開始,現在使用 Linq to XML 就不用了。
範例1:
例如,下列程式碼
//code 1
XElement el = new XElement("r",
new XElement("invoice",
new XElement("invoiceNumber", "AB12345678"),
new XElement("invoiceDate", DateTime.Now)
)
);
產生的 xml 結果如下
<r>
<invoice>
<invoiceNumber>AB12345678</invoiceNumber>
<invoiceDate>2008-09-01T10:08:22.9666505+08:00</invoiceDate>
</invoice>
</r>
這樣的方式極為簡便。
範例2:
如果要產生 namespace 呢? 以下的程式碼會產生 default namespace
//code 2
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement(ns + "r",
new XElement(ns + "invoice",
new XElement(ns + "invoiceNumber", "AB12345678"),
new XElement(ns + "invoiceDate", DateTime.Now)
));
產生如下的 xml
<r xmlns="http://www.compnay.com.tw/Invoice">
<invoice>
<invoiceNumber>AB12345678</invoiceNumber>
<invoiceDate>2008-09-01T10:16:48.2077244+08:00</invoiceDate>
</invoice>
</r>
範例3:
也可以使用如下的寫法,但效能會差一些,原因 runtime 要計算用了哪些 namespace。
//code 3
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement("{http://www.compnay.com.tw/Invoice}r",
new XElement("{http://www.compnay.com.tw/Invoice}invoice",
new XElement("{http://www.compnay.com.tw/Invoice}invoiceNumber", "AB12345678"),
new XElement("{http://www.compnay.com.tw/Invoice}invoiceDate", DateTime.Now)
)
);
結果是一樣的
<r xmlns="http://www.compnay.com.tw/Invoice">
<invoice>
<invoiceNumber>AB12345678</invoiceNumber>
<invoiceDate>2008-09-01T10:20:56.8615067+08:00</invoiceDate>
</invoice>
</r>
這樣的寫法雖然較容易了解,但較不容易修改,我個人不建議這樣的寫法。
範例4:
另外,注意到雖然我們沒有說要寫成 default namespace,但Linq to XML 會「自動」地視狀況修改。
我們可以使用 XAttribute 來使用 namesapce prefix。如下程式碼。
//code 4
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement("r",
new XAttribute(XNamespace.Xmlns + "i", "http://www.compnay.com.tw/Invoice"),
new XElement("invoice",
new XElement("invoiceNumber", "AB12345678"),
new XElement("invoiceDate", DateTime.Now)
)
);
結果如下。注意到這樣的方法,可以很方便地產生了一個 namespace prefix i,但卻沒有任何節點使用到這個 prefix
<r xmlns:i="http://www.compnay.com.tw/Invoice">
<invoice>
<invoiceNumber>AB12345678</invoiceNumber>
<invoiceDate>2008-09-01T10:27:11.773833+08:00</invoiceDate>
</invoice>
</r>
範例5:
使用下面的程式碼,就不難了解 xml namespace 的特殊
//code 5
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement("r",
new XAttribute(XNamespace.Xmlns + "i", "http://www.compnay.com.tw/Invoice"),
new XElement("{i}invoice",
new XElement("invoiceNumber", "AB12345678"),
new XElement("invoiceDate", DateTime.Now)
)
);
產生的xml 如下。xml:i="http:....." 這個 namespace 宣告了,卻沒有任何節點使用。i 是一個 namespace 的值,是inovice節點的 default namespace。invoiceNumber 與 invoiceDate的 namespace 卻是 ""。一個簡單的xml,卻有三個 namespace,基本上是錯誤的設計。
<r xmlns:i="http://www.compnay.com.tw/Invoice">
<invoice xmlns="i">
<invoiceNumber xmlns="">AB12345678</invoiceNumber>
<invoiceDate xmlns="">2008-09-01T11:02:47.1886207+08:00</invoiceDate>
</invoice>
</r>
範例6:
如果要像 code 2,產生相同的結果,但不要每一個節點使用 ns + "xxx"這樣的方式可不可以呢?如下的程式碼會發生錯誤
//code 6, fails
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement("r",
new XAttribute("xmlns", "http://www.compnay.com.tw/Invoice"),
new XElement("invoice",
new XElement("invoiceNumber", "AB12345678"),
new XElement("invoiceDate", DateTime.Now)
)
);
錯誤的訊息為 Unhandled Exception: System.Xml.XmlException: The prefix '' cannot be redefined from '' to 'http://www.compnay.com.tw/Invoice' within the same start element tag. 看來,沒有一個好的方法,將其他的節點批次地設為 default namespace了。必須每一個節點都如 code 2 一般,將每一個節點,一個個設 namespace。也沒有辦法設哪一個 namespace 為 default namespace。
範例7:
最後的範例,是 prefix namespace, 請與範例2 對照
//code 7
XNamespace ns = "http://www.compnay.com.tw/Invoice";
XElement el = new XElement(ns + "r",
new XAttribute(XNamespace.Xmlns + "i", ns),
new XElement(ns + "invoice",
new XElement(ns + "invoiceNumber", "AB12345678"),
new XElement(ns + "invoiceDate", DateTime.Now)
)
);
產生的 xml 結果如下
<i:r xmlns:i="http://www.compnay.com.tw/Invoice">
<i:invoice>
<i:invoiceNumber>AB12345678</i:invoiceNumber>
<i:invoiceDate>2008-09-02T08:52:11.4240786+08:00</i:invoiceDate>
</i:invoice>
</i:r>