Jesper Tverskov, July 24, 2008

Rename 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 rename 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 rename elements and attributes.

1. Rename element

I use the following XML document, products.xml, in many of my XML tutorials. How could we rename the product element having an attribute named "id" with a "p3" value? We want to rename the product element "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>

Renaming is like replacing except that we want to keep the original content or value. To rename 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 rename, then create another XmlNode object and navigate to the element we want to rename, then create an XmlElement object with the new element.

We must also create an object for the old content: XmlText (text only) or XmlNode (one child) or XmlNodeList (many children), and append it to the new element. Now we can use the parent element to replace old child with new child element. Since the content is the same it looks like we have renamed the element.

2. W3C DOM

2.1 rename-xml-w3cdom.aspx

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

2.2 rename-xml-w3cdom.aspx.cs

using System;
using System.Xml;

/* We want to rename an element by replacing it with a new element with the same content copied from the original element. */

public partial class rename_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 rename
    XmlNode parentElement = xmldoc.SelectSingleNode("products");

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

    // content of element we want to rename
    XmlNodeList contentXmlNodeList = xmldoc.SelectNodes("products/product[@id = 'p3']/*");

    // new element to replace old
    XmlElement newXmlElement = xmldoc.CreateElement("test");

    // old content is appended to new element
    foreach (XmlNode node in contentXmlNodeList)  
    {
      newXmlElement.AppendChild(node);
    }

    // old attributes are recreated
    foreach (XmlNode node in attXmlNodeList)
    {
      newXmlElement.SetAttribute(node.Name, node.Value);
    }

    // old element is replaced by new element (it looks like renaming)
    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. Rename attribute

Let us say that we want to rename the "id" attribute with the "p3" value. We want the "id" attribute renamed "test". Renaming 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 rename an attribute by removing it and creating a new with the same value. 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 rename. Note that when we create the XmlElement object using "xmldoc.SelectSingleNode", we must do it explicitly adding "(XmlElement)" in front of xmldoc.

We then create a string for the old value, remove the old attribute, and set the new attribute.

using System;
using System.Xml;

/* We want to rename an attribute by replacing it with a new attribute with the same value copied from the original attribute. */

public partial class rename_xml_w3cdom_a : 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 attribute we want to rename
    XmlElement parentElement = (XmlElement)xmldoc.SelectSingleNode("products/product[@id = 'p3']");

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

    // value of attribute we want to rename
    string value = xmldoc.SelectSingleNode("products/product[@id = 'p3']/@id").Value;

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

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

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

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

4. Rename XML in a namespace

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

Updated 2008-08-08