更新一個X-DOM
更新元素和attributes我們可以有以下的幾種方法:
我們也可以對XElement對象的Name屬性重新賦值達到更新目的
簡單的值更新
成員 應用於 SetValue(object) XElement, XAttribute Value XElement, XAttributeSetValue用一個簡單值更新了一個元素或者屬性的內容. 更新Value property也可以完成相當的工作, 但其只接受string數據類型.
調用SetValue或者更新Value屬性帶來的影響就是它替換了所有的子節點:
1: XElement settings = new XElement ("settings",
2: new XElement ("timeout", 30)
3: );
4: settings.SetValue ("blah");
5: Console.WriteLine (settings.ToString( ));
6:
7: // RESULT: <settings>blah</settings>
更新子節點與屬性
分類 成員 應用於 Add Add(params object[]) XContainer AddFirst(params object[]) XContainer Remove RemoveNodes() XContainer RemoveAttributes() XElement RemoveAll() XElement Update ReplaceNodes(params object[]) XContainer ReplaceAttributes(params object[]) XElement ReplaceAll(params object[]) XElement SetElementValue(XName, object) XElement SetAttributeValue(XName, object) XElement在這一組方法中最方便方法是最後兩個:SetElementValue和SetAttributeValue. 它們扮演了實例化XElement和XAttribute並將其加入一個父節點的快捷方式, 並替代了存在的指定名稱的元素或屬性.
1: XElement settings = new XElement ("settings");
2: settings.SetElementValue ("timeout", 30); // 新增子節點
3: settings.SetElementValue ("timeout", 60); // 更新子節點
Add方法添加一個子節點到一個元素或者文檔中. AddFirst也一樣, 但它將節點加入整個節點集合的開頭而不是結尾. 我們也可以通過一次調用RemoveNodes或者RemoveAttributes將所有的子節點和子屬性全部刪除. RemoveAll相當於同時調用了這兩個方法. ReplaceXXX方法等價於想調用Removing然後再次調用Adding. 對於輸入參數他們擁有一個快照, 因此e.ReplaceNodes(e.Nodes)可以如期工作.
通過Parent節點更新
成員 應用於 AddBeforeSelf(params object[]) XNode AddAfterSelf(params object[]) XNode Remove() XNode*, XAttribute* ReplaceWith(params object[]) XNode方法AddBeforeSelf, AddAfterSelf, Remove和ReplaceWith不會對當前節點的子節點進行操作. 相反, 它們操作當前節點自己所在的集合. 這要求當前節點必須擁有一個父親元素–否則, 異常將會拋出. AddBeforeSelf和AddAfterSelf對於將節點加入到任意位置是非常有用的:
1: XElement items = new XElement ("items",
2: new XElement ("one"),
3: new XElement ("three")
4: );
5: items.FirstNode.AddAfterSelf (new XElement ("two"));
輸出結果為:
1: <items><one /><two /><three /></items>
即使要在一個包含多個元素的序列當中插入任意位置的節點也是非常有效率的, 因為其內部被保存為linked list.
Remove方法從父親節點當中移除當前節點. ReplaceWith也是一樣, 但其同時插入了新的節點到相同的位置. 例如:
1: XElement items = XElement.Parse
2: ("<items><one/><two/><three/></items>");
3: items.FirstNode.ReplaceWith
4: (new XComment ("One was here"));
其結果為:
1: <items><!--one was here--><two /><three/></items>
移除序列中的節點或屬性
感謝System.Xml.Linq當中的擴展方法, 我們可以調用Remove來刪除序列中的節點或者屬性. 考慮以下下列的X-DOM:
1: XElement contacts = XElement.Parse (
2: @" <contacts>3: <customer name='Mary'/>4: <customer name='Chris' archived='true'/>5: <supplier name='Susan'>6: <phone archived='true'>7: <0123456788: <!--confidential-->9: </phone>10: </supplier>11: </contacts>");
以下的代碼刪除了所有的customers:
1: contacts.Elements ("customer").Remove();
下列的代碼則刪除所有的archived contacts(因此”Chris”將會消失)
1: contacts.Elements( )
2: .Where (e => (bool?) e.Attribute ("archived") == true)
3: .Remove( );
在內部, Remove方法首先讀取所有匹配的元素到一個臨時的列表當中, 然後枚舉該臨時列表並執行刪除操作. 這避免了在刪除的同時進行查詢操作引起的錯誤.
如果我們使用Descendants()代替Elements(), 那麼DOM當中所有archived的元素都將會消息, 我們將會得到如下的結果:
1: <contacts>
2: <customer name="Mary" />
3: <supplier name="Susan" />
4: </contacts>
下面的例子移除了所有在他們樹節點任何地方包含了”confidential”注釋的contacts:
1: contacts.Elements( )
2: .Where (
3: e => e.DescendantNodes( )
4: .OfType<XComment>( )
5: .Any (c => c.Value == "confidential")
6: ).Remove( );
結果為:
1: <contacts>
2: <customer name="Mary" />
3: <customer name="Chris" archived="true" />
4: </contacts>
如果我們使用以下的方法將會刪除所有的comment節點:
1: contacts.DescendantNodes().OfType<XComment>().Remove();
待續!