Click here to Skip to main content
Licence 
First Posted 16 May 2002
Views 155,540
Downloads 799
Bookmarked 41 times

A .NET Derived Class for Working With XML documents

By | 16 May 2002 | Article
A class derived from System.Xml.XmlDocument

Introduction

Ok, you all heard about XML, which allows you to package your data or other information in a platform independent (and easy-to-use) way.  It is no big deal, everyone can invent his/her own method to do this.  The real big deal is that a lot of people have already accepted the XML concept and there are some good tools to store, manipulate, and transport data in XML format.

The .NET Framework includes a class XmlDocument in the name space System.Xml that is really easy to use.  An XmlDocument object consists a set of XmlNode objects and each of these nodes may contain other nodes.  The XmlDocument class is derived from the XmlNode class and hence a document object is also a node.  So, an XmlDocument object is simply a tree structure.

I wrote a class XMLDocumentEx based on XmlDocument that helps you manipulate data stored in XML documents.  This class has the following methods:

// create a new node in the document object from the source node 
    //and name it as "sName"
// the return value indicates success or failure
public bool AddNode(XmlNode oSource, String sName);

// same as above except that it also specifies the parent node of the 
    // newly created node
// the return value indicates success or failure (returns false if the 
    // parent node does not exist)
public bool AddNode(XmlNode oSource, String sName, String sParent);

// create a set of new nodes in the document object from the source node
    // list and name them as "sName"
// the return value indicates success or failure
public bool AddNodes(XmlNodeList oSourceList, String sName);

// same as above except that it also specifies the parent node of the
    // newly created nodes the return value indicates success or failure
    // (returns false if the parent node 
    // does not exist)
public bool AddNodes(XmlNodeList oSourceList, String sName, String sParent);

// merge the source node into a node named "sName" in the document object
// the node named "sName" will be created if it does not exist
// the return value indicates success or failure
public bool MergeNode(XmlNode oSource, String sName);

// same as above except that it also specifies the parent node of the merged node
// the return value indicates success or failure (returns false if the parent node 
    // does not exist)
public bool MergeNode(XmlNode oSource, String sName, String sParent);

// fine print: the current versions of AddNode and MergeNode methods do not copy attributes of the source node

Examples

First, we give an example of the AddNode method.  Suppose we have two XmlDocument objects which contain the following data:

docVechile.xml

<VehicleData> 
    <Record> 
        <id>1001</id> 
        <make>Ford</make> 
        <model>Escort</model> 
        <year>1984</year> 
    </Record> 
    <Record> 
        <id>1002</id> 
        <make>Toyota</make> 
        <model>Tercel</model> 
        <year>1996</year> 
    </Record> 
    <Record> 
        <id>1003</id> 
        <make>Mazda</make> 
        <model>GLC</model> 
        <year>1985</year> 
    </Record> 
</VehicleData>

docDriver.xml

<DriverData>
    <Record>
        <id>1</id>
        <firstname>Albert</firstname>
        <lastname>Einstein</lastname>
    </Record>
    <Record>
        <id>2</id>
        <firstname>Clint</firstname>
        <lastname>Eastwood</lastname>
    </Record>
    <Record>
        <id>3</id>
        <firstname>James</firstname>
        <lastname>Bond</lastname>
    </Record>
</DriverData>

The following code will add a vehicle record and a driver record into a newly created XMLDocumentEx object:

Dim myDoc As XMLDocumentEx = New XMLDocumentEx()
myDoc.LoadXml("<Data></Data>")
myDoc.AddNode(docVehicle.SelectSingleNode("//Record"), "VehicleRecord", "Data")
myDoc.AddNode(docDriver.SelectSingleNode("//Record"), "DriverRecord", "Data")

myDoc.xml

<Data>
    <VehicleRecord>
         <id>...</id>
        <make>...</make>
        <model>...</model>
        <year>...</year>
    </ Vehicle Record>
    <DriverRecord>
        <id>...</id>
        <firstname>...</firstname>
        <lastname>...</lastname>
    </DriverRecord>
</Data>

If you want to add all vehicle and driver records to a new XMLDocumentEx object, then you can use the AddNodes method as in the following code:

Dim myDoc As XMLDocumentEx = New XMLDocumentEx()
myDoc.LoadXml("<Data> <VehicleData></Vehicle Data><DriverData></DriverData> </Data>")
myDoc.AddNodes(docVehicle.SelectNodes("//Record"), "VehicleRecord", " Vehicle Data")
myDoc.AddNodes(docDriver.SelectNodes("//Record"), "DriverRecord", "DriverData")

myDoc.xml

<Data>
     <VehicleData>
        <VehicleRecord>
            <id>1001</id>
            <make>Ford</make>
            <model>Escort</model>
            <year>1984</year>
        </VehicleRecord>
        <VehicleRecord>
            <id>1002</id>
            <make>Toyota</make>
            <model>Tercel</model>
            <year>1996</year>
        </VehicleRecord>
        <VehicleRecord>
            <id>1003</id>
            <make>Mazda</make>
            <model>GLC</model>
            <year>1985</year>
        </VehicleRecord>
    </VehicleData>
     <DriverData>
        <DriverRecord>
            <id>1</id>
            <firstname>Albert</firstname>
            <lastname>Einstein</lastname>
        </DriverRecord>
        <DriverRecord>
            <id>2</id>
            <firstname>Clint</firstname>
            <lastname>Eastwood</lastname>
        </DriverRecord>
        <DriverRecord>
            <id>3</id>
            <firstname>James</firstname>
            <lastname>Bond</lastname>
        </DriverRecord>
    </DriverData>
</Data>

Now, lets see the MergeNode method.   If  we have two XmlDocument objects docBook1, docBook2, and each of these two documents contains a <Book> node.  The <Book> node in docBook1 contains nodes <Introduction>, <Chapter1>, and <Chapter2>.  The <Book> node in docBook2 contains nodes <Chapter3>, <Chapter4>, and <Chapter5>.  The following code will merge these nodes into a new XMLDocumentEx object:

Dim myDoc As XMLDocumentEx = New XMLDocumentEx()
myDoc.LoadXml("<Data> <Book></Book></Data> ")
myDoc.MergeNode(docBook1.SelectSingleNode("//Book"), "Book", "Data ")
myDoc.MergeNode(docBook2.SelectSingleNode("//Book"), "Book", "Data")

myDoc.xml

<Data>
    <Book>
        <Introduction>...</Introduction>
        < Chapter1 >...</Chapter1>
        <Chapter2>...</Chapter2>
        <Chapter3>...</Chapter3>
        <Chapter4>...</Chapter4>
        <Chapter5>...</Chapter5>
    </Book>
</Data>

The source code

Here is the complete C# source code of the XMLDocumentEx class with comments.

sealed public class XMLDocumentEx: XmlDocument
{
    public bool AddNode(XmlNode oSource, String sName)
    {
        return AddNode(oSource, sName, null);
    }
    public bool AddNode(XmlNode oSource, String sName, String sParent)
    {
        try
        {
            if(sName!=null&&oSource!= null)
            {
                // create the new node with given name
                XmlNode oNewNode = CreateElement(sName);
                // copy the contents from the source node
                oNewNode.InnerXml = oSource.InnerXml;
                // if there is no parent node specified, then add
                // the new node as a child node of the root node
                if(sParent!= null) sParent = sParent.Trim();
                if(sParent== null||sParent.Equals(String.Empty)) 
                {
                    DocumentElement.AppendChild(oNewNode);
                    return true;
                }
                // otherwise add the new node as a child of the parent node
                else
                {
                    if (!sParent.Substring(0,2).Equals("//")) sParent = "//"+sParent;
                    XmlNode oParent = SelectSingleNode(sParent);
                    if (oParent!=null)
                    {
                        oParent.AppendChild(oNewNode);
                        return true ;
                    }
                }
            }
        }
        catch (Exception)
        {
            // error handling code
        }
        return false;
    }
    public bool AddNodes(XmlNodeList oSourceList, String sName)
    {
        return AddNodes(oSourceList, sName, null);
    }
    public bool AddNodes(XmlNodeList oSourceList, String sName, String sParent)
    {
        try
        {
            if(oSourceList!= null)
            {
                // call AddNode for each item in the source node list
                // return true only if all nodes are added successfully
                int i = 0;
                while(i<oSourceList.Count)
                {
                    if (!AddNode(oSourceList.Item(i),sName,sParent)) return false;
                    i++;
                }
                return true;
            }
        }
        catch (Exception)
        {
            // error handling code
        }
        return false;
    }
    public bool MergeNode(XmlNode oSource, String sName)
    {
        return MergeNode(oSource, sName, null );
    }
    public bool MergeNode(XmlNode oSource, String sName, String sParent)
    {
        try
        {
            if(sName!=null&&oSource!= null)
            {
                XmlNode theNode = null ;
                // if there is no parent node specified ...
                if(sParent!= null) sParent = sParent.Trim();
                if(sParent== null||sParent.Equals(String.Empty)) 
                {
                    // if the node with specified name does not exist,
                    // add it as a child node of the root node
                    theNode = SelectSingleNode("//"+sName);
                    if (theNode==null)
                    {
                        theNode = CreateElement(sName);
                        DocumentElement.AppendChild(theNode);
                    }
                }
                // if the parent node is specified ...
                else
                {
                    // find the parent node
                    if (!sParent.Substring(0,2).Equals("//")) sParent = "//"+sParent;
                    XmlNode theParent = SelectSingleNode(sParent);
                    if (theParent!=null)
                    {
                        // if the node with specified name does not exist, create
                        // it first, then add it as a child node of the parent node
                        theNode = theParent.SelectSingleNode(sName);
                        if(theNode==null)
                        {
                            theNode = CreateElement(sName);
                            theParent.AppendChild(theNode);
                        }
                    }
                }
                // merge the content of the source node into
                // the node with specified name
                if(theNode!= null) 
                {
                    theNode.InnerXml += oSource.InnerXml;
                    return true;
                }
            }
        }
        catch (Exception)
        {
        }
        return false;
    }
}

Thanks for reading.  Check out my home page for other articles and tools .

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralAbout SOAP & interoperability between java & asp.net Pinmembershindesanjiv19:47 2 Aug '06  
GeneralYou know... Pinmembereyoung705:38 24 Sep '04  
GeneralRe: You know... PinmemberXiangyang Liu6:17 24 Sep '04  
GeneralHelp me! PinmemberTanoFaye2:19 16 Jan '04  
GeneralRe: Help me! PinmemberXiangyang Liu4:12 16 Jan '04  
GeneralOops PinmemberNood!e9:45 16 Sep '02  
GeneralUpdate 2002/05/28 PinmemberXiangyang Liu6:43 28 May '02  
GeneralNice article... PinmemberNish - Native CPian0:07 18 May '02  
GeneralRe: Nice article... PinmemberXiangYangLiu3:25 18 May '02  
GeneralRe: Nice article... PinmemberNish - Native CPian15:44 19 May '02  
GeneralRe: Nice article... PineditorPaul Watson4:02 3 Jun '02  
GeneralRe: Nice article... PinmemberXiangYangLiu4:25 3 Jun '02  
GeneralRe: Nice article... PineditorPaul Watson21:50 3 Jun '02  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 17 May 2002
Article Copyright 2002 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid