Recipe15.3.Querying the Contents of an XML Document


Recipe 15.3. Querying the Contents of an XML Document

Problem

You have a large and complex XML document and you need to find various pieces of information, such as all the information contained within a specific element and having a particular attribute setting. You want to query the XML structure without having to iterate through all the nodes in the XML document and search for a particular item by hand.

Solution

To query a database, you normally use SQL. To query an XML document, you currently use XPath or with SQL Server 2005 possibly XQuery (as .NET 2.0 does not support it as part of the Base Class Library [BCL.NET]). In .NET, this means using the System.Xml.XPath namespace and classes like XPathDocument, XPathNavigator, and XPathNodeIterator.

In the following example, you use these classes to select nodes from an XML document that holds members from the board game Clue (or Cluedo, as it is known abroad) and their various roles. You want to be able to select the married female participants who were witnesses to the crime. In order to do this, pass an XPath expression to query the XML dataset as shown in Example 15-2.

Example 15-2. Querying an XML document

 public static void QueryXML( )  {     string xmlFragment = "<?xml version='1.0'?>" +         "<Clue>" +         "<Participant type='Perpetrator'>Professor Plum</Participant>" +         "<Participant type='Witness'>Colonel Mustard</Participant>" +         "<Participant type='Witness'>Mrs. White</Participant>" +         "<Participant type='Witness'>Mrs. Peacock</Participant>" +         "<Participant type='Witness'>Mr. Green</Participant>" +         "</Clue>";     using (StringReader reader = new StringReader(xmlFragment))     {         // Instantiate an XPathDocument using the StringReader.         XPathDocument xpathDoc = new XPathDocument(reader);         // Get the navigator.         XPathNavigator xpathNav = xpathDoc.CreateNavigator();         // Get up the query looking for the married female participants         // who were witnesses.         string xpathQuery =             "/Clue/Participant[attribute::type='Witness'][contains(text(),'Mrs.')]";          XPathExpression xpathExpr = xpathNav.Compile(xpathQuery);         // Get the nodeset from the compiled expression.         XPathNodeIterator xpathIter = xpathNav.Select(xpathExpr);         // Write out the nodes found (Mrs. White and Mrs.Peacock in this instance).         while (xpathIter.MoveNext())         {             Console.WriteLine(xpathIter.Current.Value);         }     }  } 

This outputs the following:

 Mrs. White Mrs. Peacock 

Discussion

XPath is a very versatile language for performing queries on XML-based data. In order to accomplish this goal, you first create an XML fragment that looks like this:

 <?xml version='1.0'?> <Clue>     <Participant type='Perpetrator'>Professor Plum</Participant>     <Participant type='Witness'>Colonel Mustard</Participant>     <Participant type='Witness'>Mrs. White</Participant>     <Participant type='Witness'>Mrs. Peacock</Participant>     <Participant type='Witness'>Mr. Green</Participant> </Clue>; 

You then load this fragment into a StringReader, then construct an XPathDocument to allow you to create an XPathNavigator. This lets you use XPath syntax to query the XML document shown in the preceding listing. The XPathDocument instance wraps the MemoryStream so you can use XPath to locate nodes (as well as perform XSLT transforms directly), and the XPathNavigator gets the set of nodes selected by the XPath expression.

 byte[] bytes = Encoding.UTF8.GetBytes(xmlFragment); MemoryStream memStream = new MemoryStream(bytes); // Instantiate an XPathDocument using the MemoryStream. XPathDocument xpathDoc = new XPathDocument(memStream); // Get the navigator. XPathNavigator xpathNav = xpathDoc.CreateNavigator(); 

Now you have to determine the XPath-based query to get all of the married female participants who were witnesses. This is set up in the xpathQuery string like this:

 // Get up the query looking for the married female participants // who were witnesses. string xpathQuery =   "/Clue/Participant[attribute::type='Witness'][contains(text( ),'Mrs.')]"; 

To help you grasp what is going on here, let's look at the syntax:

  • /Clue/Participant says "Get all of the Participants under the root-level node Clue."

  • Participant[attribute::type='Witness'] says "Select only Participants with an attribute called type with a value of Witness."

  • Participant[contains(text( ),'Mrs.')] says "Select only Participants with a value that contains 'Mrs.'"

Put them all together and you get all of the married female participants who were witnesses.

Once you have an XPathNavigator, call the Select method on it, passing the XPath-based query to select the nodes you are looking for. These are returned via the XPathNodeIterator. You use the XPathNodeIterator to write out the names of the participants you found and close the MemoryStream.

See Also

See the "XPathDocument Class," "XPathNavigator Enumeration," and "XPathNode-Iterator Class" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net