An XmlDocument
can easily be loaded from disk using the Load( )
method. It has overloads for a Stream
, filename,
TextReader
, or XmlReader
, and
the LoadXml( )
method will load an XML string from
memory. This provides great flexibility; you can load an
XmlDocument
from a file, a web site, standard
input, a memory buffer, or any subclass of Stream
or TextReader
, as well as any subclass of
XmlReader
.
For example, suppose the inventory file were stored on a web server,
at http://www.angushardware.com/inventory.xml
.
The following code would let you read it:
XmlDocument document = new XmlDocument( ); document.Load("http://www.angushardware.com/inventory.xml");
After
reading the entire document into memory, you now have non-sequential
access to the entire XML tree. For example, you could easily navigate
down to the number of each item in stock using the
XmlNode
type’s
SelectNodes( )
method. SelectNodes(
)
returns an XmlNodeList
based on an
XPath expression; in this case, you’re selecting all
nodes that match the expression //items/item
, and
writing them to the console:
XmlDocument document = new XmlDocument( ); document.Load("http://www.angushardware.com/inventory.xml"); XmlNodeList items = document.SelectNodes("//items/item"); foreach (XmlElement item in items) { Console.WriteLine("{0} units of product code {1} in stock", item.GetAttribute("quantity"), item.GetAttribute("productCode")); }
XPath is covered in Chapter 6.
Although you don’t
necessarily know in what order the items will appear in the inventory
file, you might want to print out the inventory in some reasonable
order, such as by product code. While an XML Schema can alert you if
elements in an XML document are in the wrong order, it
can’t ensure that elements are ordered by an
attribute value. To do this, you can create a
private inner class called UnitInventory
to hold a
single product type’s inventory information. This
class will implement the IComparable
interface to
permit easy sorting, and you can override ToString(
)
to use the same object to print the inventory:
private class UnitInventory : IComparable { private string productCode; private int quantity; private string description; private double unitCost; public UnitInventory(string productCode, string quantity, string description, string unitCost) { this.productCode = productCode; this.quantity = Int32.Parse(quantity); this.description = description; this.unitCost = Double.Parse(unitCost); } public int CompareTo(object other) { UnitInventory otherInventory = (UnitInventory)other; return productCode.CompareTo(otherInventory.productCode); } public override string ToString( ) { return quantity + " units of product code " + productCode + ", '" + description + "', in stock at $" + unitCost; } }
Now you can create an instance of UnitInventory
for each row returned by SelectNodes( )
, add each
to an ArrayList
and sort the list, and, finally,
write each item to the console:
XmlDocument document = new XmlDocument( ); document.Load("http://www.angushardware.com/inventory.xml"); XmlNodeList items = document.SelectNodes("//items/item"); ArrayList list = new ArrayList(items.Count); foreach (XmlElement item in items) { list.Add(new UnitInventory(item.GetAttribute("productCode"), item.GetAttribute("quantity"), item.GetAttribute("description"), item.GetAttribute("unitCost"))); } list.Sort( ); foreach (UnitInventory inventory in list) { Console.WriteLine(inventory); }
If you run the program, you’ll see the list of
inventory items sorted by the productCode
attribute:
23 units of product code 1632S, '12 Piece Drill Bit Set', in stock at $14.95 15 units of product code R-273, '14.4 Volt Cordless Drill', in stock at $189.95
3.22.181.47