5.11. Edit an XML Document with XPathNavigator
The XPathNavigator is the XML interface of choice for Visual Basic 2005 applications. And in .NET 2.0, it doesn't just work as a view onto read-only XML datait also allows you to change XML documents, such as by modifying text content, inserting new elements, or removing a branch of nodes.
Note: The best feature of the XPathNavigator is its new support for editing and inserting content.
5.11.1. How do I do that?
In the previous lab, Section 5.10, you learned how to load XML data into an XPathDocument, and then browse and search through it using an XPathNavigator. If you want to make changes, you still start with the same XPathDocument. The secret is that you also use a couple of additional methods in the XPathNavigator:
Remember, you have two basic choices for creating an XPathNavigator:
Example 5-12 modifies the XML document shown in Example 5-10. It increases all the prices by 10% and then deletes nodes that don't fall into the Tools category. Finally, it displays the altered XML document.
Example 5-12. Modifying an XML document with XPathNavigator
Imports System.Xml.XPath Imports System.Xml Module XPathNavigatorTest Sub Main( ) ' Load the document. Dim Doc As New XPathDocument(My.Computer.FileSystem.CurrentDirectory & _ "\ProductList.xml") ' Use the XPathNavigator to make updates. Dim XPathIterator As XPathNodeIterator = Doc.Select("//UnitCost") ' Increase the price by 10%. For Each Editor As XPathNavigator In XPathIterator Editor.SetValue((1.1 * Editor.ValueAsDouble).ToString( )) Next ' Delete nodes that aren't in the Tools category. XPathIterator = Doc.Select("/Products/Product[CategoryName!='Tools']") For Each Editor As XPathNavigator In XPathIterator Editor.DeleteCurrent( ) Next ' Show changes. XPathEditor.MoveToRoot( ) Console.WriteLine(XPathEditor.OuterXml) End Sub End Module
When you run this application, the XML for the changed document is displayed in the console window. You can also open the ProductList_new.xml file where the changes are saved.
In many cases, you won't just want to change a valueyou'll need a way to insert new elements or entire sections. The XPathNavigator includes a handful of methods for inserting new elements and attributes in one shot. However, the easiest way to add a block of XML is to use an XmlWriter. If you've worked with XML and .NET before, you probably recognize the XmlWriter. The XmlWriter was commonly used to write XML content directly to a file in .NET 1.x applications. The difference in .NET 2.0 is that the XPathEditor allows you to use the XmlWriter to write directly to your in-memory XPathDocument.
All you need to do is start by calling one of the XPathEditor methods that returns an XmlWriter. These include the following, which differ on where each places the inserted XML:
Example 5-13 uses the AppendChild() method to add a new product to the product list XML document.
Example 5-13. Using the AppendChild( ) method to add a new element to an XML document
Imports System.Xml.XPath Imports System.Xml Module XPathNavigatorTest Sub Main( ) ' Load the document. Dim Doc As New XPathDocument(My.Computer.FileSystem.CurrentDirectory & _ "\ProductList.xml") ' Create a new product. Dim XPathEditor As XPathNavigator = Doc.CreateEditor( ) XPathEditor.MoveToRoot( ) XPathEditor.MoveToFirstChild( ) ' Use the XmlWriter to add a new <Product> complete with ' all child elements. Dim Writer As XmlWriter = XPathEditor.AppendChild ' Insert the opening <Product> tag. Writer.WriteStartElement("Product", _ "http://www.ibuyspy.com/ProductCatalog") ' The WriteElementString( ) method inserts a whole element at once. Writer.WriteElementString("ProductID", "999") Writer.WriteElementString("ModelName", "Rubber Pants") Writer.WriteElementString("ModelNumber", "NOZ999") Writer.WriteElementString("UnitCost", "12.99") Writer.WriteElementString("CategoryName", "Clothing") ' Insert the closing </Product> tag and close the writer. Writer.WriteEndElement( ) Writer.Close( ) ' Show changes. XPathEditor.MoveToRoot( ) Console.WriteLine(XPathEditor.OuterXml) End Sub End Module
Running Example 5-13 generates the following XML, which is displayed in the console window and saved to the newly generated XML file:
... <Product> <ProductID>999</ProductID> <ModelName>Rubber Pants</ModelName> <ModelNumber>NOZ999</ModelNumber> <UnitCost>12.99</UnitCost> <CategoryName>Clothing</CategoryName> </Product> ...
Note: You can create multiple navigator and editor objects to work with the same XPathDocument. However, the editors don't perform any locking, so you can't edit an XPathDocument on multiple threads at the same time unless you take your own safeguards.
5.11.2. What about...
...validating your XML? The XPathNavigator and the XmlWriter both force you to write valid XML. However, it's also important to check XML documents to make sure they match specific rules. The best tool for this task is an XML schema document that defines the elements, structure, data types, and constraints for a document.
The actual schema standard is beyond the scope of this chapter. (For a good introduction, refer to the tutorial at http://www.w3schools.com/schema.) However, assuming you have a schema for your XML, you can validate your document at any time by calling XPathNavigator.CheckValidity(). This method returns true if the document conforms to the schema. Here's how to do it:
' Load the document. Dim Doc As New XPathDocument("c:\ProductList.xml") ' (Make updates). ' Load the schema. ' Technically, you can load a collection of schemas, ' one for each namespace in the document that you want to validate. Dim Schemas As New XmlSchemaSet( ) Schemas.Add("http://www.ibuyspy.com/ProductCatalog", "c:\ProductListSchema.xsd") Schemas.Compile( ) ' Validate with the schema. ' Instead of submitting a null reference (Nothing), you can supply ' a delegate that points to a callback method that will be triggered ' every time an error is found when the validation check is performed. Dim Valid As Boolean Valid = Doc.CreateNavigator( ).CheckValidity(Schemas, Nothing)
5.11.3. Where can I learn more?
For more information about editing the XPathDocument, look up the "XPathNavigator class" index entry in the MSDN Help. If you've used earlier betas of .NET 2.0, which included the same features in a different class ( XPathEditableNavigator), you may want to refer to http://blogs.msdn.com/dareobasanjo/archive/2004/09/03/225070.aspx for some explanation straight from Microsoft bloggers.