Click here to Skip to main content
Click here to Skip to main content
Go to top

Insert XML Nodes Using XmlTextReader and XmlTextWriter

, 29 Jan 2004
Rate this:
Please Sign up or sign in to vote.
Using XmlTextReader and XmlTextWriter to insert an XML document within another document without creating an XmlDocument object

Introduction

XmlDocument objects are easy to use for navigating the DOM and copying, modifying, or inserting nodes. However, they can also use a large amount of memory to store the entire DOM of a large XML string in memory. Because of this, the XmlReader and XmlWriter classes are used for stream based manipulation of an XML string.

Using the code

The insert method illustrates the process of reading two strings of XML with the XmlTextReader from the System.Xml namespace to ensure they are both valid XML. The source XML is read to ensure its validity and then stored in a StringBuilder object. The target XML is read, but the root element is stripped off and the name and attributes and stored in string variables. The inner XML from the target document is read and stored in another StringBuilder object. Finally the XmlTextWriter is used to write out the root element and its attributes with the source XML inserted before the inner XML from the target document.

Start off with the insert method declaration.

private string insert(string sourceXml, string targetXml)
{
...
}

First, the XmlTextReader and XmlTextWriter objects must be created and initialized with the sourceXml string.

// Declare and set readers and writers for sourceXml
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringReader stringReader = 
  new System.IO.StringReader(sourceXml);
System.IO.StringWriter stringWriter = 
  new System.IO.StringWriter(sb);

System.Xml.XmlTextReader xmlReader = 
  new System.Xml.XmlTextReader(stringReader);
System.Xml.XmlTextWriter xmlWriter = 
  new System.Xml.XmlTextWriter(stringWriter);

string strValidSourceXml = String.Empty;
string strValidTargetXml = String.Empty;

string strRootName = String.Empty;
string[,] arrRootAtts = null;

The source XML is read, validated, and written into the StringBuilder object by parsing each node with the XmlReader and subsequently writing each node to the StringBuilder with the XmlWriter.

try
{
  while(xmlReader.Read())
  {
    xmlWriter.WriteNode(xmlReader,true);
  }
}
catch(System.Xml.XmlException e)
{
  MessageBox.Show(this,
    "Error parsing source XML\n\nMessage: " + e.Message,
    "Parser Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
  return String.Empty;
}
strValidSourceXml = sb.ToString();

After reading the source, the readers and writers must be reset to parse the target XML.

// Reset readers and writers for targetXml
sb = new System.Text.StringBuilder();
stringReader = new System.IO.StringReader(targetXml);
stringWriter = new System.IO.StringWriter(sb);
xmlReader = new System.Xml.XmlTextReader(stringReader);
xmlWriter = new System.Xml.XmlTextWriter(stringWriter);

Then the root element is broken into its components - name and attributes. The inner XML from the root is read into a string variable.

try
{
  while(xmlReader.Read())
  {
    // Parse root node and store name and attributes
    strRootName = xmlReader.Name;
    if(xmlReader.HasAttributes)
    {
      int i = 0;
      arrRootAtts = new string[xmlReader.AttributeCount,2];
      while(xmlReader.MoveToNextAttribute())
      {
        arrRootAtts[i,0] = xmlReader.Name;
        arrRootAtts[i,1] = xmlReader.Value;
        i++;
      }
    }
    // Store inner XML as string
    strValidTargetXml = xmlReader.ReadInnerXml();
  }
}
catch(System.Xml.XmlException e)
{
  MessageBox.Show(this,
    "Error parsing target XML\n\nMessage: " + e.Message,
    "Parser Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
  return String.Empty;
}

The root node and its attributes are written out to a StringBuilder using the XmlWriter. The validated XML from the source and the inner XML from the target are written as children of the root node.

// Combine root node with source and target XML strings
xmlWriter.WriteStartElement(strRootName);
if (arrRootAtts != null)
{
  for (int i = 0; i < arrRootAtts.GetLength(0); i++)
  {
    xmlWriter.WriteAttributeString(arrRootAtts[i,0],
      arrRootAtts[i,1]);
  }
}
xmlWriter.WriteRaw(strValidTargetXml + strValidSourceXml);
xmlWriter.WriteEndElement();

Finally, the method returns the string from the StringBuilder object containing the combined XML as a string.

return sb.ToString();

Memory Savings

Be aware that the StringBuilder and the strings themselves carry some memory overhead, so it's often worth taking time to compare the two approaches for typical strings of XML and determine if the memory savings is worth the extra development effort.

In my testing, for combining two strings of XML, using the XmlReader resulted in 1/2 the memory consumption of the XmlDocument approach.

While the XmlDocument object is certainly more intuitive for inserting nodes into a string of XML, the XmlReader and XmlWriter objects can be utilized for quickly parsing and combining large strings of XML with less memory overhead than using the XmlDocument and XmlDocumentFragment objects to combine two documents.

History

  • Posted - 1/29/2004

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

Share

About the Author

Dave Curylo, MCAD
Web Developer
United States United States
Systems Analyst specializing in Java and C# development.

Comments and Discussions

 
GeneralMy vote of 5 Pinmembersam2222210-Feb-13 23:23 
GeneralThe lesser code way PinmemberMads Nissen2-Jun-04 21:33 
GeneralRe: The lesser code way PinmemberMotoMan0455-Feb-05 13:18 

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.

| Advertise | Privacy | Mobile
Web03 | 2.8.140926.1 | Last Updated 30 Jan 2004
Article Copyright 2004 by Dave Curylo, MCAD
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid