Export (0) Print
Expand All

Insert XML Data using XPathNavigator

The XPathNavigator class provides a set of methods used to insert sibling, child, and attribute nodes in an XML document. In order to use these methods, the XPathNavigator object must be editable, that is, its CanEdit property must be true.

XPathNavigator objects that can edit an XML document are created by the CreateNavigator method of the XmlDocument class. XPathNavigator objects created by the XPathDocument class are read-only and any attempt to use the editing methods of an XPathNavigator object created by an XPathDocument object results in a NotSupportedException.

For more information about creating editable XPathNavigator objects, see Reading XML Data using XPathDocument and XmlDocument.

The XPathNavigator class provides methods to insert sibling, child, and attribute nodes in an XML document. These methods allow you to insert nodes and attributes in different locations in relation to the current position of an XPathNavigator object and are described in the following sections.

The XPathNavigator class provides the following methods to insert sibling nodes.

These methods insert sibling nodes before and after the node an XPathNavigator object is currently positioned on.

The InsertAfter and InsertBefore methods are overloaded and accept a string, XmlReader object, or XPathNavigator object containing the sibling node to add as parameters. Both methods also return an XmlWriter object used to insert sibling nodes.

The InsertElementAfter and InsertElementBefore methods insert a single sibling node before and after the node an XPathNavigator object is currently positioned on using the namespace prefix, local name, namespace URI, and value specified as parameters.

In the following example a new pages element is inserted before the price child element of the first book element in the contosoBooks.xml file.

XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");
navigator.MoveToChild("price", "http://www.contoso.com/books");

navigator.InsertBefore("<pages>100</pages>");

navigator.MoveToParent();
Console.WriteLine(navigator.OuterXml);

The example takes the contosoBooks.xml file as an input.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

For more information about the InsertAfter, InsertBefore, InsertElementAfter and InsertElementBefore methods, see the XPathNavigator class reference documentation.

The XPathNavigator class provides the following methods to insert child nodes.

These methods append and prepend child nodes to the end of and the beginning of the list of child nodes of the node an XPathNavigator object is currently positioned on.

Like the methods in the "Inserting Sibling Nodes" section, the AppendChild and PrependChild methods accept a string, XmlReader object, or XPathNavigator object containing the child node to add as parameters. Both methods also return an XmlWriter object used to insert child nodes.

Also like the methods in the "Inserting Sibling Nodes" section, the AppendChildElement and PrependChildElement methods insert a single child node to the end of and the beginning of the list of child nodes of the node an XPathNavigator object is currently positioned on using the namespace prefix, local name, namespace URI, and value specified as parameters.

In the following example, a new pages child element is appended to the list of child elements of the first book element in the contosoBooks.xml file.

XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");

navigator.AppendChild("<pages>100</pages>");

Console.WriteLine(navigator.OuterXml);

The example takes the contosoBooks.xml file as an input.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

For more information about the AppendChild, PrependChild, AppendChildElement and PrependChildElement methods, see the XPathNavigator class reference documentation.

The XPathNavigator class provides the following methods to insert attribute nodes.

These methods insert attribute nodes on the element node an XPathNavigator object is currently positioned on. The CreateAttribute method creates an attribute node on the element node an XPathNavigator object is currently positioned on using the namespace prefix, local name, namespace URI, and value specified as parameters. The CreateAttributes method returns an XmlWriter object used to insert attribute nodes.

In the following example, new discount and currency attributes are created on the price child element of the first book element in the contosoBooks.xml file using the XmlWriter object returned from the CreateAttributes method.

XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");
navigator.MoveToChild("price", "http://www.contoso.com/books");

XmlWriter attributes = navigator.CreateAttributes();

attributes.WriteAttributeString("discount", "1.00");
attributes.WriteAttributeString("currency", "USD");
attributes.Close();

navigator.MoveToParent();
Console.WriteLine(navigator.OuterXml);

The example takes the contosoBooks.xml file as an input.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

For more information about the CreateAttribute and CreateAttributes methods, see the XPathNavigator class reference documentation.

In certain cases you may want to populate an XML document with the contents from another XML document. Both the XPathNavigator class and the XmlWriter class can copy nodes to an XmlDocument object from an existing XmlReader object or XPathNavigator object.

The AppendChild, PrependChild, InsertBefore and InsertAfter methods of the XPathNavigator class all have overloads that can accept an XPathNavigator object or an XmlReader object as a parameter.

The WriteNode method of the XmlWriter class has overloads that can accept an XmlNode, XmlReader, or XPathNavigator object.

The following example copies all the book elements from one document to another.

XmlDocument document = new XmlDocument();
document.Load("books.xml");
XPathNavigator navigator = document.CreateNavigator();

navigator.MoveToChild("bookstore", String.Empty);
            
XPathDocument newBooks = new XPathDocument("newBooks.xml");
XPathNavigator newBooksNavigator = newBooks.CreateNavigator();

foreach (XPathNavigator nav in newBooksNavigator.SelectDescendants("book", "", false))
{
    navigator.AppendChild(nav);
}

document.Save("newBooks.xml");

The XPathNavigator class provides the SetValue and SetTypedValue methods to insert values for a node into an XmlDocument object.

The SetValue method simply inserts the untyped string value passed as a parameter as the value of the node the XPathNavigator object is currently positioned on. The value is inserted without any type or without verifying that the new value is valid according to the type of the node if schema information is available.

In the following example, the SetValue method is used to update all price elements in the contosoBooks.xml file.

XmlDocument document = new XmlDocument();
document.Load("contosoBooks.xml");
XPathNavigator navigator = document.CreateNavigator();

XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("bk", "http://www.contoso.com/books");

foreach (XPathNavigator nav in navigator.Select("//bk:price", manager))
{
    if (nav.Value == "11.99")
    {
        nav.SetValue("12.99");
    }
}

Console.WriteLine(navigator.OuterXml);

The example takes the contosoBooks.xml file as an input.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

When the type of a node is a W3C XML Schema simple type, the new value inserted by the SetTypedValue method is checked against the facets of the simple type before the value is set. If the new value is not valid according to the type of the node (for example, setting a value of -1 on an element whose type is xs:positiveInteger), it results in an exception.

The following example attempts to change the value of the price element of the first book element in the contosoBooks.xml file to a DateTime value. Because the XML Schema type of the price element is defined as xs:decimal in the contosoBooks.xsd files, this results in an exception.

XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd");
settings.ValidationType = ValidationType.Schema;

XmlReader reader = XmlReader.Create("contosoBooks.xml", settings);

XmlDocument document = new XmlDocument();
document.Load(reader);
XPathNavigator navigator = document.CreateNavigator();

navigator.MoveToChild("bookstore", "http://www.contoso.com/books");
navigator.MoveToChild("book", "http://www.contoso.com/books");
navigator.MoveToChild("price", "http://www.contoso.com/books");

navigator.SetTypedValue(DateTime.Now);

The example takes the contosoBooks.xml file as an input.

<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://www.contoso.com/books">
    <book genre="autobiography" publicationdate="1981-03-22" ISBN="1-861003-11-0">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
            <first-name>Benjamin</first-name>
            <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
    </book>
    <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2">
        <title>The Confidence Man</title>
        <author>
            <first-name>Herman</first-name>
            <last-name>Melville</last-name>
        </author>
        <price>11.99</price>
    </book>
    <book genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6">
        <title>The Gorgias</title>
        <author>
            <name>Plato</name>
        </author>
        <price>9.99</price>
    </book>
</bookstore>

The example also takes the contosoBooks.xsd as an input.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="bookstore">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="book">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="title" type="xs:string" />
                            <xs:element name="author">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element minOccurs="0" name="name" type="xs:string" />
                                        <xs:element minOccurs="0" name="first-name" type="xs:string" />
                                        <xs:element minOccurs="0" name="last-name" type="xs:string" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="price" type="xs:decimal" />
                        </xs:sequence>
                        <xs:attribute name="genre" type="xs:string" use="required" />
                        <xs:attribute name="publicationdate" type="xs:date" use="required" />
                        <xs:attribute name="ISBN" type="xs:string" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

The InnerXml and OuterXml properties of the XPathNavigator class change the XML markup of the nodes an XPathNavigator object is currently positioned on.

The InnerXml property changes the XML markup of the child nodes an XPathNavigator object is currently positioned on with the parsed contents of the given XML string. Similarly, the OuterXml property changes the XML markup of the child nodes an XPathNavigator object is currently positioned on as well as the current node itself.

In addition to the methods described in this topic, the InnerXml and OuterXml properties can be used to insert nodes and values in an XML document. For more information about using the InnerXml and OuterXml properties to insert nodes and values, see the Modify XML Data using XPathNavigator topic.

Certain conflicts related to the scope of namespace and xml:lang declarations can occur when inserting XML data using the InsertBefore, InsertAfter, AppendChild and PrependChild methods of the XPathNavigator class that take XmlReader objects as parameters.

The following are the possible namespace conflicts.

  • If there is a namespace in-scope within the XmlReader object's context, where the prefix to namespace URI mapping is not in the XPathNavigator object's context, a new namespace declaration is added to the newly inserted node.

  • If the same namespace URI is in-scope within both the XmlReader object's context and the XPathNavigator object's context, but has a different prefix mapped to it in both contexts, a new namespace declaration is added to the newly inserted node, with the prefix and namespace URI taken from the XmlReader object.

  • If the same namespace prefix is in-scope within both the XmlReader object's context and the XPathNavigator object's context, but has a different namespace URI mapped to it in both contexts, a new namespace declaration is added to the newly inserted node which re-declares that prefix with the namespace URI taken from XmlReader object.

  • If the prefix as well as the namespace URI in both the XmlReader object's context and the XPathNavigator object's context is the same, no new namespace declaration is added to the newly inserted node.

Note Note

The description above also applies to namespace declarations with the empty string as a prefix (for example, the default namespace declaration).

The following are the possible xml:lang conflicts.

  • If there is an xml:lang attribute in-scope within the XmlReader object's context but not in the XPathNavigator object's context, an xml:lang attribute whose value is taken from the XmlReader object is added to the newly inserted node.

  • If there is an xml:lang attribute in-scope within both the XmlReader object's context and the XPathNavigator object's context, but each has a different value, an xml:lang attribute whose value is taken from the XmlReader object is added to the newly inserted node.

  • If there is an xml:lang attribute in-scope within both the XmlReader object's context and the XPathNavigator object's context, but each with the same value, no new xml:lang attribute is added on the newly inserted node.

  • If there is an xml:lang attribute in-scope within the XPathNavigator object's context, but none existing in the XmlReader object's context, no xml:lang attribute is added to the newly inserted node.

The methods used to insert sibling, child and attribute nodes described in the "Inserting Nodes and Values" section are overloaded. The InsertAfter, InsertBefore, AppendChild, PrependChild and CreateAttributes methods of the XPathNavigator class return an XmlWriter object used to insert nodes.

Not all of the methods used for writing information to an XML document using the XmlWriter class are supported by the XPathNavigator class due to difference between the XPath data model and the Document Object Model (DOM).

The following table describes the XmlWriter class methods not supported by the XPathNavigator class.

Method

Description

WriteEntityRef

Throws a NotSupportedException exception.

WriteDocType

Ignored at the root level and throws a NotSupportedException exception if called at any other level in the XML document.

WriteCData

Treated as a call to the WriteString method for the equivalent character or characters.

WriteCharEntity

Treated as a call to the WriteString method for the equivalent character or characters.

WriteSurrogateCharEntity

Treated as a call to the WriteString method for the equivalent character or characters.

For more information about the XmlWriter class, see the XmlWriter class reference documentation.

It is possible to have multiple XPathNavigator objects pointing to different parts of an XML document with one or more open XmlWriter objects. Multiple XmlWriter objects are allowed and supported in single-threaded scenarios.

The following are important notes to consider when using multiple XmlWriter objects.

  • XML fragments written by XmlWriter objects are added to the XML document when the Close method of each XmlWriter object is called. Until that point, the XmlWriter object is writing a disconnected fragment. If an operation is performed on the XML document, any fragments being written by an XmlWriter object, before the Close has been called, are not affected.

  • If there is an open XmlWriter object on a particular XML subtree and that subtree is deleted, the XmlWriter object may still add to the sub-tree. The subtree simply becomes a deleted fragment.

  • If multiple XmlWriter objects are opened at the same point in the XML document, they are added to the XML document in the order in which the XmlWriter objects are closed, not in the order in which they were opened.

The following example creates an XmlDocument object, creates an XPathNavigator object, and then uses the XmlWriter object returned by the PrependChild method to create the structure of the first book in the books.xml file. The example then saves it as the book.xml file.

XmlDocument document = new XmlDocument();
XPathNavigator navigator = document.CreateNavigator();

using (XmlWriter writer = navigator.PrependChild())
{
    writer.WriteStartElement("bookstore");
    writer.WriteStartElement("book");
    writer.WriteAttributeString("genre", "autobiography");
    writer.WriteAttributeString("publicationdate", "1981-03-22");
    writer.WriteAttributeString("ISBN", "1-861003-11-0");
    writer.WriteElementString("title", "The Autobiography of Benjamin Franklin");
    writer.WriteStartElement("author");
    writer.WriteElementString("first-name", "Benjamin");
    writer.WriteElementString("last-name", "Franklin");
    writer.WriteElementString("price", "8.99");
    writer.WriteEndElement();
    writer.WriteEndElement();
    writer.WriteEndElement();
}
document.Save("book.xml");

Saving changes made to an XmlDocument object as the result of the methods described in this topic is performed using the methods of the XmlDocument class. For more information about saving changes made to an XmlDocument object, see Saving and Writing a Document.

Show:
© 2014 Microsoft