To modify an XML file with XDocument
, you load the file into a variable of type XDocument
, modify it in memory, then save it, overwriting the original file.
A common mistake is to modify the XML in memory and expect the file on disk to change.
Given an XML file:
<?xml version="1.0" encoding="utf-8"?>
<FruitBasket xmlns="http://www.fruitauthority.fake">
<Fruit>
<FruitName>Banana</FruitName>
<FruitColor>Yellow</FruitColor>
</Fruit>
<Fruit>
<FruitName>Apple</FruitName>
<FruitColor>Red</FruitColor>
</Fruit>
</FruitBasket>
You want to modify the Banana's color to brown:
XDocument.Load
receives a URI (file path)..
used in this query has the potential to return a null set if the condition finds no elements. Before C# 6 you would do this in multiple steps, checking for null along the way. The result is the <Fruit>
element that contains the Banana. Actually an IEnumerable<XElement>
, which is why the next step uses FirstOfDefault()
.XDocument
, overwriting the original file on disk.// 1.
string xmlFilePath = "c:\\users\\public\\fruit.xml";
// 2.
XDocument xdoc = XDocument.Load(xmlFilePath);
// 3.
XNamespace ns = "http://www.fruitauthority.fake";
//4.
var elBanana = xdoc.Descendants()?.
Elements(ns + "FruitName")?.
Where(x => x.Value == "Banana")?.
Ancestors(ns + "Fruit");
// 5.
var elColor = elBanana.Elements(ns + "FruitColor").FirstOrDefault();
// 6.
if (elColor != null)
{
elColor.Value = "Brown";
}
// 7.
xdoc.Save(xmlFilePath);
The file now looks like this:
<?xml version="1.0" encoding="utf-8"?>
<FruitBasket xmlns="http://www.fruitauthority.fake">
<Fruit>
<FruitName>Banana</FruitName>
<FruitColor>Brown</FruitColor>
</Fruit>
<Fruit>
<FruitName>Apple</FruitName>
<FruitColor>Red</FruitColor>
</Fruit>
</FruitBasket>