Recently a colleague needed a quick and easy way to replace the text in a specific element in over 1000 XML files. And he needed a solution NOW. There are probably a few ways this could be done without writing a line of code but I was intrigued be the coding challenge it provided.
I decided to use a console application would it would give me the quickest start. The main method of the application gets a list of all XML files in the same folder as the executable. For each file in the list it calls an XMLReplace method.
static void Main(string[] args)
{
// Get the path to the directory
var path = AppDomain.CurrentDomain.BaseDirectory;
// Get all files in the path
var files = Directory.GetFiles(path);
foreach (var filePath in files.Where(p => Path.GetExtension(p) == ".xml"))
{
// for each xml file do the required actions
Console.WriteLine(Path.GetFileName(filePath));
XMLReplace(filePath);
}
}
This is the XML schema I will be using in this example. The actual files I was given contained a much more complex schema.
<?xml version="1.0" encoding="utf-8" ?>
<contacts>
<contact>
<firstname>Charlie</firstname>
<lastname>Wilks</lastname>
<address>
<street>Sea View</street>
<city>Marley</city>
<county>Manshire</county>
<postcode>MA9 7BS</postcode>
<country></country>
</address>
</contact>
</contacts>
The XMLReplace method contains the code that replaces the text of the XML element.
static void XMLReplace(string filePath)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
var elem = xmlDoc.SelectSingleNode("/contacts/contact/address/country");
if (elem != null)
{
elem.InnerText = "UK";
//xmlDoc.Save(filePath);
XmlTextWriter wr = new XmlTextWriter(filePath, Encoding.UTF8);
wr.Formatting = Formatting.None;
xmlDoc.Save(wr);
}
else
{
Console.WriteLine("Element not found!");
}
}
The first thing the method does is to load the XML document from the path parameter and search for the element. The SelectSingleNode function returns the first match even if the file contained multiple address elements. If a match is found the text is set to UK.
It is possible to save the file by calling the Save method of the XML document object passing in the path of the save location. But when the file is saved it will be formatted with line breaks. As we did not want formatting in the files I had, an XMLTextWriter was used. Setting the formatting to none saves the file with no formatting (line breaks or indentation etc) all text just comes out on a single line.
At this point I had a working solution which my colleague was very happy with. It works fine for files where an element only occurs once, but what about schemas where an element is repeated and all occurrences need to be set.
This can be accommodated with just a few changes to the XMLReplace method.
Firstly, instead of calling the SelectSingleNode function of the XmlDocument object the GetElementsByTagName function is can be called which returns all occurrences of an element. The GetElementsByTagName function accepts a string parameter which in this case is just the name of the element and not the whole hierarchical from the root to the required element. As there may be multiple elements found these can be iterated and the contents set to the desired string. Saving the XML back to the file is done with a XmlTextWriter as before.
static void XMLReplaceMultiple(string filePath)
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(filePath);
var elements = xmlDoc.GetElementsByTagName("country");
for (int looper = 0; looper < elements.Count; looper++ )
{
elements.Item(looper).InnerText = "UK";
}
//xmlDoc.Save(filePath);
XmlTextWriter wr = new XmlTextWriter(filePath, Encoding.UTF8);
wr.Formatting = Formatting.None;
xmlDoc.Save(wr);
}
That’s it for now, enjoy.

You must be logged in to post a comment.