Jesper Tverskov, August 5, 2008

Update 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 update 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 update elements and attributes.

1. Update element

I use the following XML document, products.xml, in many of my XML tutorials. How could we update the "country" element of the "p3" product to become "China" or "<p>China</p>"?

<?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>

W3C DOM is not easy because the standard (Recommendation) is not for the end-user but for the programmer implementing the interface in some programming language. What of W3C DOM is actually implemented in the language we are using, and what are just confusing extensions in that language not part of W3C DOM?

Updating elements and attributes is awkward in pure W3C DOM. One way is to remove the existing content and to add the new content first created the hard way. We can not blame Microsoft for adding extentions like "InnerXml" and "InnerText" to make things much easier. The following code shows four ways of updating an element. Three of the four must be deleted or out-commented if you want to use the code for real.

2. W3C DOM

2.1 update-xml-w3cdom.aspx

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

2.2 update-xml-w3cdom.aspx.cs

using System;
using System.Xml;

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

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

      // NOTE: 3 of 4 solutions must be deleted or out-commented

      // a) pure W3C DOM = text
      XmlText newContent = xmldoc.CreateTextNode("China");
      xmlNode.RemoveAll();
      xmlNode.AppendChild(newContent);

      // b) pure W3C DOM = markup + text
      XmlElement newXmlElement = xmldoc.CreateElement("p");
      XmlText newContent = xmldoc.CreateTextNode("China");
      newXmlElement.AppendChild(newContent);
      xmlNode.RemoveAll();
      xmlNode.AppendChild(newXmlElement);

      // c) Microsoft InnerText extension = text
      xmlNode.InnerText = "China";

      // d) Microsoft InnerXml extension = markup + text
      xmlNode.InnerXml = "<p>China</p>";

      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. Add attribute

Let us say that we want to change the "p3" value of the "id" attribute to "p10". The "Value" property is a Microsoft extension to W3C DOM but we can't blame Microsoft for reducing three lines of code to one. In the following we show both ways. One of them must be deleted or out-commented if you want to use the code for real.

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

// attribute we want to update
XmlNode xmlNode = xmldoc.SelectSingleNode("products/product[@id = 'p3']/@id");

// NOTE: 1 of 2 solutions must be deleted or out-commented

// a) pure W3C DOM
XmlText newValue = xmldoc.CreateTextNode("p10");
xmlNode.RemoveAll();
xmlNode.AppendChild(newValue);

// b) Microsoft Value extension
xmlNode.Value = "p10";

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

4. Update XML in a namespace

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

Updated 2008-08-05