Getting Started with XML
Requirements: IPWorks
Contents
Introduction
The XML component offers a fast and simple way to parse, write, and modify XML documents. This guide shows how to use each of these features, with examples in C#.
When a document is parsed, the component builds an internal object model (DOM) of the document, which can then be navigated with the XPath property. If a DOM is not needed, the BuildDOM property can be set to false, in which case the document is parsed in a forward-only manner and the parsed data are provided only through events.
Documents are written from beginning to end in a forward-only manner, by calling methods such as StartElement and PutElement. A parsed document can also be modified (e.g., by inserting, changing, or removing elements and attributes) and then saved.
Parsing
To parse a document, first specify the input. The component checks the input properties in the following order, and uses the first one that is set:
- SetInputStream (.NET and Java only)
- InputFile
- InputData
Then call the Parse method. While the document is parsed, events such as StartElement, Characters, and EndElement fire. If BuildDOM is true (default), the document can be navigated by setting XPath after Parse returns. To parse another document with the same instance, call the Reset method first.
The examples in this guide use the following document:
<?xml version="1.0"?>
<weatherdata station="KRDU">
<reading time="08:00">
<temp unit="F">54</temp>
<humidity>81</humidity>
</reading>
<reading time="12:00">
<temp unit="F">66</temp>
<humidity>57</humidity>
</reading>
</weatherdata>
XML xml = new XML();
xml.InputFile = "C:\\temp\\weatherdata.xml";
xml.Parse();
Navigating with XPath
The XPath property implements a subset of the XPath specification. A path is a series of element accessors separated by /, and paths that do not begin with / are relative to the current element. Unlike in the JSON component, there is no added root element, so absolute paths begin with the name of the root element of the document (e.g., /weatherdata).
| Accessor | Description |
|---|---|
| name | The first child element with the specified name. |
| name[i] | The i-th child element with the specified name (1-based). |
| [i] | The i-th child element (1-based). |
| [last()] | The last child element ([last()-i] is also supported). |
| name[@attr='value'] | The child element with the specified name and attribute value. |
| .. | The parent of the current element. |
When XPath is set to a valid path, the following properties are populated with information about the element at that path:
| Property | Description |
|---|---|
| XElement | The name of the element. |
| XText | The text of the element. |
| XParent | The name of the parent of the element. |
| XNamespace and XPrefix | The namespace and prefix of the element. |
| XAttributes | A collection of the attributes of the element, each with a Name, Value, Namespace, and Prefix. |
| XChildren | A collection of the child elements of the element, each with a Name, XText, Namespace, and Prefix. |
| XSubTree | The XML of the element and its children. |
The value of a single attribute of the current element can also be retrieved with the GetAttr method, which returns an empty string if the attribute does not exist.
// Get the temperature of the second reading, and its unit.
xml.XPath = "/weatherdata/reading[2]/temp";
Console.WriteLine(xml.XText + " " + xml.GetAttr("unit")); // Prints 66 F.
// Get the humidity of the reading with a time attribute of 08:00.
xml.XPath = "/weatherdata/reading[@time='08:00']/humidity";
Console.WriteLine(xml.XText); // Prints 81.
// Get the temperature of the last reading.
xml.XPath = "/weatherdata/reading[last()]/temp";
Console.WriteLine(xml.XText); // Prints 66.
// Get the temperature of the first reading, relative to the root element.
xml.XPath = "/weatherdata";
xml.XPath = "reading[1]/temp";
Console.WriteLine(xml.XText); // Prints 54.
The following code prints the time and temperature of every reading, using XChildren:
xml.XPath = "/weatherdata";
int readingCount = xml.XChildren.Count;
for (int i = 1; i <= readingCount; i++)
{
xml.XPath = "/weatherdata/reading[" + i + "]";
string time = xml.GetAttr("time");
xml.XPath = "temp";
Console.WriteLine(time + ": " + xml.XText + " " + xml.GetAttr("unit"));
}
This prints:
08:00: 54 F
12:00: 66 F
If the path does not exist in the document, setting XPath throws an exception. To check whether a path exists first, use the HasXPath method, or use the TryXPath method, which sets XPath only if the path exists and returns whether it does.
if (xml.TryXPath("/weatherdata/reading[1]/rainfall"))
{
Console.WriteLine(xml.XText);
}
else
{
Console.WriteLine("No rainfall data.");
}
Forward-Only Parsing
If the document does not need to be navigated, set BuildDOM to false before calling Parse. This reduces the memory usage and increases the performance of the parser, which is especially useful for large documents, and the parsed data are then provided only through the events. Within the StartElement event, the attributes of the element can be retrieved with GetAttr or XAttributes.
XML xml = new XML();
xml.BuildDOM = false;
xml.OnStartElement += (s, e) =>
{
// Print the time attribute of each reading element.
if (e.Element == "reading") Console.WriteLine("Reading at " + xml.GetAttr("time"));
};
xml.OnCharacters += (s, e) => { Console.WriteLine("Characters: " + e.Text); };
xml.InputFile = "C:\\temp\\weatherdata.xml";
xml.Parse();
This prints:
Reading at 08:00
Characters: 54
Characters: 81
Reading at 12:00
Characters: 66
Characters: 57
Alternatively, to keep BuildDOM enabled while reducing memory usage, the RemoveElement or RemoveChildren method can be called in the EndElement event to remove sections of the document that are no longer needed.
Writing
To write a document, first specify the output. The component checks the output properties in the following order, and uses the first one that is set:
- SetOutputStream (.NET and Java only)
- OutputFile
- OutputData (used if no other output is specified)
When OutputFile is used, the Overwrite property must be set to true if the file already exists, or an exception is thrown.
The document is then written from beginning to end with the following methods:
| Method | Description |
|---|---|
| StartElement | Writes the opening tag of an element, as a child of the currently open element. |
| PutAttr | Writes an attribute in the element that was just opened, and must be called before any content is written to the element. |
| PutElement | Writes a complete element with a text value and no attributes. |
| PutString | Writes text, which is escaped automatically (e.g., < is written as <). |
| PutCData, PutComment, and PutRaw | Write a CDATA section, a comment, or raw text that is not escaped. |
| EndElement | Writes the closing tag of the most recently opened element. |
When the document is complete, call the Save method, which closes any elements that are still open. As the document is written, the XML event also fires with each part of the document in its Text parameter. By default, the output begins with an XML declaration, and is indented with tabs and separated into lines with CRLF. These can be changed with the IncludeXMLDeclaration, Indent, and EOL configuration settings.
XML xml = new XML();
xml.OutputFile = "C:\\temp\\weatherdata.xml";
xml.Overwrite = true;
xml.StartElement("weatherdata", "");
xml.PutAttr("station", "", "KRDU");
xml.StartElement("reading", "");
xml.PutAttr("time", "", "08:00");
// Write an element with an attribute and a value.
xml.StartElement("temp", "");
xml.PutAttr("unit", "", "F");
xml.PutString("54");
xml.EndElement();
// Write an element with only a value.
xml.PutElement("humidity", "", "81");
xml.EndElement();
xml.EndElement();
xml.Save();
This writes:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<weatherdata station="KRDU">
<reading time="08:00">
<temp unit="F">54</temp>
<humidity>81</humidity>
</reading>
</weatherdata>
The second parameter of StartElement, PutElement, and PutAttr is the namespace URI of the element or attribute, which can be left empty if namespaces are not used. For an example of writing a document with namespaces, please see the documentation of the StartElement method.
Note that these methods always write a new document. To add elements to a document that was parsed, use InsertElement as described in the next section.
Modifying
After a document is parsed with BuildDOM set to true, it can be modified with the following methods and properties, which operate on the element that XPath points to:
| Method or Property | Description |
|---|---|
| XText | Setting this property changes the text of the element. |
| InsertElement | Adds a new child element, with the specified text, after the existing children of the element. |
| InsertAttr | Adds a new attribute to the element, and throws an exception if the attribute already exists. |
| SetAttr | Changes the value of an existing attribute, and throws an exception if the attribute does not exist. |
| RemoveAttr | Removes an attribute from the element. |
| RemoveElement | Removes the element and its children. |
| RemoveChildren | Removes the children of the element, but not the element itself. |
When the changes are complete, call Save to write the modified document to the output, which is specified in the same way as when writing a document.
XML xml = new XML();
xml.InputFile = "C:\\temp\\weatherdata.xml";
xml.Parse();
// Change the temperature of the first reading, and its unit.
xml.XPath = "/weatherdata/reading[1]/temp";
xml.XText = "12";
xml.SetAttr("unit", "", "C");
// Add a rainfall element to the first reading.
xml.XPath = "/weatherdata/reading[1]";
xml.InsertElement("rainfall", "", "0.12");
// Add an attribute to the root element.
xml.XPath = "/weatherdata";
xml.InsertAttr("updated", "", "2026-11-03");
// Remove the second reading.
xml.XPath = "/weatherdata/reading[2]";
xml.RemoveElement();
// Write the modified document back to the same file.
xml.OutputFile = "C:\\temp\\weatherdata.xml";
xml.Overwrite = true;
xml.Save();
This writes:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<weatherdata station="KRDU" updated="2026-11-03">
<reading time="08:00">
<temp unit="C">12</temp>
<humidity>81</humidity>
<rainfall>0.12</rainfall>
</reading>
</weatherdata>
We appreciate your feedback. If you have any questions, comments, or suggestions about this article please contact our support team at support@nsoftware.com.