Jesper Tverskov, July 17, 2008

Replace XML with W3C DOM in ASP.NET

In ASP.NET we have two main APIs for editing XML: W3C DOM and LINQ to XML. In this tutorial we look at how to replace elements and attributes in W3C DOM. There are many more properties and methods and ways of achieving the same result than shown below. You must look up the proper documentation for all the details.

Editing XML basically consists of the following: adding, deleting or replacing elements and attributes, and updating content of elements and values of attributes. An API for editing also has properties and methods for comments, processing instructions, etc, but in this tutorial we only look at how to replace elements and attributes.

1. Replace element

I use the following XML document, products.xml, in many of my XML tutorials. How could we replace the product element having an attribute named "id" with a "p3" value? We want to replace the product element with "<test>abc</test>".

<?xml version="1.0" encoding="utf-8"?>
<products>
  <product id="p1">
    <name>Delta</name>
    <price>800</price>
    <stock>4</stock>
    <country>Denmark</country>
  </product>
  ...
  <product id="p3">
    <name>Alfa</name>
    <price>1200</price>
    <stock>19</stock>
    <country>Germany</country>
  </product>
  ...
</products>

To replace an element we must first create an XmlDocument object and load the XML document into it, then create an XmlNode object and navigate to the parent element of the element we want to replace, then create another XmlNode object and navigate to the element we want to replace, then create an XmlElement object with the new element and an XmlText object and append it to the new element.

Now we can use the parent element to replace old child with new child element.

2. W3C DOM

2.1 replace-xml-w3cdom.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="remove-xml-w3cdom.aspx.cs" Inherits="replace_xml_w3cdom" %>

2.2 replace-xml-w3cdom.aspx.cs

using System;
using System.Xml;

public partial class replace_xml_w3cdom : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
    {
      XmlDocument xmldoc = new XmlDocument();
      xmldoc.Load(Server.MapPath("products.xml"));

      // parent element of the element we want to replace
      XmlNode parentElement = xmldoc.SelectSingleNode("products");

      // element we want to replace
      XmlNode oldXmlNode = xmldoc.SelectSingleNode("products/product[@id = 'p3']");

      // new element
      XmlElement newXmlElement = xmldoc.CreateElement("test");
      // content for new element
      XmlText newText = xmldoc.CreateTextNode("abc");
      newXmlElement.AppendChild(newText);      // old element is replaced by new element
      parentElement.ReplaceChild(newXmlElement, oldXmlNode);

      xmldoc.Save(Server.MapPath("products.xml"));

      Response.Redirect("products.xml"); // load file in browser
    }
}

The W3C DOM API takes more code than LINQ to XML but the nice thing about W3C DOM is that it is a standard API implemented by most programming languages. We can even read or edit an HTML document more or less the same using the HTML version of W3C DOM.

3. Replace attribute

Let us say that we want to replace the "id" attribute with the "p3" value. We want a new "test" attribute with the value "abc". Replacing attributes are known to cause problems for many users. Attributes are not children of their parent element (!): we must choose properties and methods carefully. See: Accessing Attributes in the DOM, at MSDN.

We can only replace an attribute by removing it and creating a new. The easiest way is to create an XmlElement object for the parent of the attribute instead of just an XmlNode object, and an XmlAttribute object for the attribute we want to remove. Note that when we create the XmlElement object using "xmldoc.SelectSingleNode", we must do it explicitly adding "(XmlElement)" in front of xmldoc.

XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(Server.MapPath("products.xml"));

// parent element of the attribute we want to replace
XmlElement parentElement = (XmlElement)xmldoc.SelectSingleNode("products/product[@id = 'p3']");

// attribute we want to replace
XmlAttribute oldXmlAttribute = parentElement.GetAttributeNode("id");

// old attribute is removed
parentElement.RemoveAttributeNode(oldXmlAttribute);

// new attribute is created
parentElement.SetAttribute("test", "abc");

xmldoc.Save(Server.MapPath("products.xml"));

4. Replace XML in a namespace

See: Read XML with W3C DOM for how to use XmlNameSpaceManager.

Updated 2008-08-08