XML in the Microsoft .NET Framework

By: John Ray Thomas

Abstract: XML is used throughout the Microsoft .NET Framework. This tutorial provides a basic understanding of what is provided and how you can use it in your applications.

John Ray Thomas (JT) is a product manager for the RAD Business Unit at Borland. He is an avid game and graphics programmer and is a big fan of alternative operating systems. JT is also a student of business and engineering at San Jose State University and lives in Santa Cruz with his wife, Jessica, and baby daughter, Izabella.

jthomas@borland.com

XML in the Microsoft .NET Framework

Borland Developers Conference 2004

Authored by Robert Love

 

Introduction.. 2

Reading an XML Document.. 2

Reading with XmlReader Descendants. 2

Reading with XmlDocument 5

Reading with XmlDataDocument 7

Reading with the XPathNavigator Class. 7

Writing an Xml Document.. 9

Writing with XmlWriter 9

Writing with XmlDocument 10

Writing with XmlDataDocument 11

Xml Object Serialization.. 12

What is Object Serialization?. 12

How to use XmlSerializer 12

Controlling Serialization through Attributes. 14

Performing XSLT Transformations.. 15

Tools.. 15

Appendix.. 17

Training Example Xml Document 17

XPath. 17

Getting Started with XPath. 17

Relative Paths. 18

Path Wildcards. 19

Current and Prior Node. 20

XPath Axes. 21

XPath Predicates. 22

Accessing Attributes. 23

XPath Expression. 24

XPath Functions. 26

XSLT.. 29

XSLT Declaration. 29

Matching and Applying Templates. 29

value-of element 31

for-each element 32

Extending Templates. 33

Recommended References.. 35

Contact Information.. 36

 


Introduction

XML has become an industry standard and is universally accepted. It is used in a number of different ways. The .NET framework is no exception. There are many different and unique ways XML is used in the .NET Framework. This document will attempt to show some common XML tasks, and how to address these using the classes in the framework.

 

Reading an XML Document

There are many built-in ways to read an Xml Document, each with its own benefits. Understanding these benefits and associated drawbacks, will help you in determining which class is the correct one to use.

 

Some of the ways to read an Xml Document in the .NET Framework

  • The Abstract XmlReader Class Descendants
    • XmlTextReader
    • XmlValidatingReader
    • XmlNodeReader
  • The XmlDocument Class and Descendants
    • XmlDataDocument
  • The XPathDocument Class
  • The ReadXml Method of Dataset
  • Classes in System.Xml.Serialization Namespace

 

Reading with XmlReader Descendants

 

XmlReader provides an abstract model for accessing Xml Data. XmlReader descendants provide a Read Only, Uni-Directional view of an Xml Document. They also provide an easy interface to walk an Xml document from beginning to end.

 

There are three built in XmlReader Descendants

Class

Purpose

XmlTextReader

Read an Xml document stream or file with out validating to a schema or a Document Type Definition (DTD).

XmlNodeReader

Read from an XmlNode descendant such as XmlDocument which is the .NET DOM Implementation.

XmlValidatingReader

Read an Xml Document Stream or File, allowing it to be validated to a schema or a Document Type Definition (DTD).

 

When using XmlTextReader or XmlValidatingReader you can keep your memory footprint lower, since the entire document does not need to be loaded in memory. This makes these classes very useful for large files where the file size is greater than the available memory. The XmlNodeReader does not have this benefit as it is reading from an XmlNode descendant. Typically this XmlNode is an XmlDocument which already has loaded the entire document in to memory.

 

The XmlReader provides several methods to assist you in walking through all parts of an Xml Document. Each of these is very well documented in the .NET SDK Help File. I dont intend to cover all of these, only the essential methods needed to do basic parsing.

 

When reading with an XmlReader each part of the Xml document is separated in to a node. For example, the following XML structure would be broken into five different nodes.

 

<example><name>value</name></example>

Document Part

Node Type

<example>

XmlNodeType.Element

<name>

XmlNodeType.Element

Value

XmlNodeType.Text

</name>

XmlNodeType.EndElement

</example>

XmlNodeType.EndElement

 

When constructing an instance of an XmlReader descendant you specify the source of the Xml Document. In the case of XmlTextReader you have many different overloaded constructors allowing you to specify many different types of sources, such as the file name or stream that contains the Xml document. The XmlNodeReader needs an XmlNode as the source document; typically this is an XmlDocument class. The overloaded constructors for the XmlValidatingReader can accept a stream, string, or another XmlReader descendant as parameters.

 

After the XmlReader descendant instance has been constructed you call the Read method to read in the first node. Then using one of the many XmlReader properties you can access the details regarding that node, such as NodeType, Name and Value. You can then continue to call the Read method to loop through the entire document. When the Read method returns false you have reached the end of the document.

 

The following uses an XmlTextReader to loop through a specified file and add all the element names in the Xml document to a ListBox.

Var

xr : XmlTextReader;

begin

xr := XmlTextReader.Create(txtFileName.Text);

while xr.Read Do

begin

if xr.NodeType = XmlNodeType.Element then

ListBox1.Items.Add(xr.Name);

end;

end;

 

 

 

The following uses an XmlTextReader to loop through a specified file, adding the text values to the list box where the element name is PHONE. Notice how you must call Read again to get the node that contains the text value of the phone number.

Delphi for .NET

Var

xr : XmlTextReader;

begin

xr := XmlTextReader.Create(txtFileName.Text);

while xr.Read Do

begin

if (xr.NodeType = XmlNodeType.Element) and (xr.Name = 'PHONE') then

begin

if Not xr.Read then Break;

ListBox1.Items.Add(xr.Value);

end;

end;

 

The XmlValidatingReader provides an event named ValidationEventHandler. This event is used to notify your application of a validation error that may occur when looping through the document.

 

The following example demonstrates the use of the ValidationEventHandler to validate the specified document.

/// Validation Event

procedure TMyWinForm.ValidationEvent(sender: Tobject;

args: ValidationEventArgs);

begin

isValid := False;

ValidErrorMsg := args.Message;

end;

 

// Button Click that opens document and validates it.

procedure TMyWinForm.ValidateBtn_Click(sender: System.Object; e: System.EventArgs);

var

tr : XmlTextReader;

vr : XmlValidatingReader;

begin

// isValid is Declared in the Class, default to being valid

isValid := True;

 

// Construct the XmlTextReader

tr := XmlTextReader.Create(txtFileName.Text);

 

// Construct the Validating Reader Passing the XmlTextReader

vr := XmlValidatingReader.Create(tr);

 

// Attach Event Handler to be Notified if error occurs.

Include(vr.ValidationEventHandler,ValidationEvent);

 

// Read through all nodes of the file

while vr.Read do;

 

// Check if isValid was set to true in the event and what message occurred.

if Not isValid then

MessageBox.Show(ValidErrorMsg)

else

MessageBox.Show('Document is Valid');

end;

 

 

Reading with XmlDocument

 

The XmlDocument class implements the Xml DOM specification. Since DOM is a W3C standardized API, much of the functionality is similar between different implementations. When an XmlDocument is constructed the entire Xml document is parsed and stored as a tree in memory. This gives you bi-directional navigation, with the ability to make changes to the XmlDocument in memory. Since the entire document is in memory the class is not practical to use with large Xml documents.

 

After an XmlDocument is constructed you must call Load, or LoadXML to specify the source document. The document source can be one of many different things including a String, File, Stream, or XmlReader. No Validating is done on the document, if you need the document validated you should use an XmlValidatingReader to retrieve the source document. The XmlDocument provides many methods to navigate and work with an Xml Document. The .NET SDK Documentation is an excellent source of information on all of the methods that are provided by the XmlDocument Class. This paper will attempt to show how to use some of these methods.

 

The key class when dealing with an XmlDocument is an XmlNode. An XmlNode can have any number of attributes and child XmlNodes. In fact, XmlDocument is a descendant of XmlNode with a few additional methods and properties, such as those used to read and write an Xml document.

 

The XmlNode Child Nodes can be accessed through the following properties:

ChildNodes, FirstChild, LastNode, PreviousSibling, NextSibling. The ChildNodes contain the array of all nodes which can be looped through, using either a for loop or a while loop.

There are also two other key methods that allow you to execute an XPath Statement and return a single node, or set of nodes: SelectSingleNode and SelectNodes. These methods are very useful as they prevent you from having to walk the document tree to get what you are after. Instead, you can specify an XPath Query that will return the XmlNode(s) you are after.

 

The following example uses a FOR loop (via Index) to navigate all of the children of the root element adding their names to a ListBox.

Var

XmlDoc : XmlDocument;

I : Integer;

RootNode : XmlNode;

begin

XmlDoc := XmlDocument.Create;

XmlDoc.Load(txtFileName.Text);

// Select the Root Node

RootNode := XmlDoc.SelectSingleNode('/*');

// Loop Through all of the Child Nodes of the Root and Display their names

For I := 0 to RootNode.ChildNodes.Count -1 do

ListBox1.Items.Add(RootNode.ChildNodes.Item(I).Name);

end;

 

The following example uses a FOR loop (via Delphi 9 in Construct) to navigate all of the children of the root element adding their names to a ListBox.

Var

XmlDoc : XmlDocument;

I : Integer;

RootNode : XmlNode;

ChildNode : XmlNode;

begin

XmlDoc := XmlDocument.Create;

XmlDoc.Load(txtFileName.Text);

// Select the Root Node

RootNode := XmlDoc.SelectSingleNode('/*');

// Loop Through all of the Child Nodes of the Root and Display their names

For ChildNode in RootNode.ChildNodes do

ListBox1.Items.Add(ChildNode.Name);

end;

 


 

 

The following example uses a WHILE loop to navigate all of the children of the root element, adding their names to a ListBox.

Var

XmlDoc : XmlDocument;

RootNode : XmlNode;

ChildNode : XmlNode;

begin

XmlDoc := XmlDocument.Create;

XmlDoc.Load(txtFileName.Text);

// Select the Root Node

RootNode := XmlDoc.SelectSingleNode('/*');

ChildNode := RootNode.FirstChild;

// Loop Through all of the Child Nodes of the Root and Display their names

While Assigned(ChildNode) do

begin

ListBox1.Items.Add(ChildNode.Name);

ChildNode := ChildNode.NextSibling;

end;

end;

 

Reading with XmlDataDocument

 

The XmlDataDocument descends from XmlDocument and is enhanced to load and save data to and from a Dataset. This can be a useful method to data bind visual controls to an Xml Document.

 

In order to load an Xml Document with XmlDataDocument you will need a schema that describes the Document. This document tells the XmlDataDocument how to layout the tables and rows in the DataSet class.

 

First you must call the ReadXmlSchema method of the XmlDataDocument Class to pass the schema of the document. Then you can call Load to load the document desired.

 

Then you can use the DataSet Property to work with the Xml Document as a DataSet, or you can work with XmlDataDocument just like you would with XmlDocument.

 

Reading with the XPathNavigator Class

 

The XPathNavigator class is one of my favorite methods for reading Xml Documents. Used in combination with the XPathDocument Class, It provides a fast and efficient way to query data stored in an Xml Document. The only draw back to using XPathDocument is that it is read only. However, with .NET 2.0 XPathDocument will add the ability to modify the document. Microsoft has already started to recommend using XPathDocument over XmlDocument where possible. If you are unfamiliar with XPath, I suggest you skip to the appendix section on XPath found on Page 18.

 

The most important method on the XPathDocument class is CreateNavigator which creates the XPathNavigator that allows you navigate the document. There are many ways to use the XPath Navigator. In the Example below I show how to use the Select method to create an XpathNodeIterator to loop through the results of an XPath Query.

var

xNavDoc : XPathDocument;

xNav : XPathNavigator;

Nodes : XPathNodeIterator;

begin

xNavDoc := XPathDocument.Create('C:DEMOCLIENTLIST.XML');

xNav := xNavDoc.CreateNavigator;

Nodes := xNav.Select('/CLIENTLIST/CLIENT/PHONE');

while Nodes.MoveNext do

begin

ListBox1.Items.Add(Nodes.Current.Value);

end;

end;

 


Writing an Xml Document

 

There are many built-in ways to write an Xml Document, each has its own benefits. Understanding these benefits and associated drawbacks, will help you in determining which class is the correct one to use.

 

Some of the ways to write an Xml Document in the .NET Framework

  • The Abstract XmlWriter Class Descendant
    • XmlTextWriter
  • The XmlDocument Class and Descendants
    • XmlDataDocument
  • The WriteXml Method of DataSet
  • Classes in System.Xml.Serialization Namespace

 

 

Writing with XmlWriter

 

The XmlWriter is an abstract class. The framework provides only one decendant the XmlTextWriter. The XmlWriter provides the basic functionality required to create Xml. You can create both Xml documents and document fragements using the XmlWriter. It is possible to create non-well formed Xml Documents with XmlWriter so care must be taken to verify that your output is well formed. The XmlWriter is a very fast and efficent method to output Xml. For the most part, the other Framework classes that create Xml are output through the XmlTextWriter. I personally find the XmlWriter to be the easiest way to write Xml Documents.

 

Using an XmlWriter to produce the XML for an RSS feed.

Delphi for .NET

function TWinForm3.BasicRSSFeed: string;

var

XW : XmlTextWriter;

SW : StringWriter;

begin

SW := StringWriter.Create;

XW := XmlTextWriter.Create(SW);

 

XW.WriteStartDocument;

XW.WriteStartElement('rss');

XW.WriteAttributeString('version','2.0');

XW.WriteStartElement('channel');

XW.WriteElementString('title','Title of My Feed');

XW.WriteElementString('link','http://linktomyfeed/');

XW.WriteElementString('description','Description of my Feed');

XW.WriteStartElement('item');

XW.WriteElementString('title','Item Title');

XW.WriteElementString('description','This is the content');

XW.WriteElementString('pubdate',DateTime.Now.ToUniversalTime.ToString('r'));

XW.WriteEndElement; //item

XW.WriteEndElement; // channel

XW.WriteEndElement; // rss

XW.WriteEndDocument;

XW.Close;

SW.Close;

result := SW.ToString;

end;

 

Writing with XmlDocument

 

XmlDocument can be used to write Xml Documents, as well as read them.

 

<?xml version="1.0" encoding="utf-16"?>
<events>
<event name="BorCon">
<location>San Jose</location>
</event>
</events>

 

The following function demostrates how to create the above document using XmlDocument.

 

function CreateSampleDocument : String;

var

DOM : XmlDocument;

RootNode : XmlNode;

EventNode : XmlNode;

LocationNode : XmlNode;

AttrNode : XmlAttribute;

writer : StringWriter;

begin

DOM := XmlDocument.Create;

// Create Root Node

RootNode := DOM.CreateElement('events');

// Append Root Model

DOM.AppendChild(RootNode);

 

// Create Event Node

// Note: This has the same effect as calling CreateElement

// CreateNode can be used to create all the different element types

EventNode := DOM.CreateNode(XmlNodeType.Element,'event','');

 

// Create and Add Attribute to EventNode

AttrNode := DOM.CreateAttribute('name');

AttrNode.Value := 'BorCon';

EventNode.Attributes.Append(AttrNode);

 

// Create and Add Location to Event Node

LocationNode := DOM.CreateElement('location');

LocationNode.InnerText := 'San Jose';

EventNode.AppendChild(LocationNode);

 

// Append Event Node to Root Node

RootNode.AppendChild(EventNode);

 

// Create StringWriter for Save

writer := StringWriter.Create;

// Save is overloaded and can take one of the following as params

// XmlWriter, TextWriter, FileName, Stream

DOM.Save(writer);

 

// output String Result

result := writer.ToString;

end;

Writing with XmlDataDocument

One of the common problems you may face in development is exporting relation data into a text based format, such as XML.    This can be accomplished using XmlDataDocument which represents your relational data as an XmlDocument.  The XmlDataDocument can then be used as a source to an XSLT Transformation to produce the output document.
   

  1. Create a Dataset with the contents from your Database.
  2. Create an XmlDataDocument passing the DataSet that is filled with your database content.
  3. Create an XslTransform and Load the XSLT document that will transform your dataset XML document into the resulting feed format.
  4. Call Transform on the XslTranform which will place your output into one of many formats. In the example below I am using a StringWriter.

 

Var
XDD : XmlDataDocument;
SW : StringWriter;
XT : XslTransform;

DS : DataSet;
begin
BdpDataAdapter1.Fill(DS);
XDD := XmlDataDocument.Create(DS);
SW := StringWriter.Create();
XT := XslTransform.Create;
XT.Load('C:DEMOSTRANSFORM.XSL');
XT.Transform(XDD,nil,SW);
TextBox1.Text := SW.ToString;
end;

 


Xml Object Serialization

What is Object Serialization?

 

Serialization allows you to convert an object to a persistent medium, such as a file. Then at any given time the object can be de-serialized and loaded with values from the previously persistent state. One common application of serialization is with web services, allowing your web methods to return objects. The returning objects will be serialized as Xml, allowing them to be transmitted over the wire.

 

The .Net Framework provides everything you need to serialize an object in Xml Format.

 

There are some restrictions on Xml serialization.

  • Only public properties and fields can be serialized.
  • A class must have a default constructor to be serialized.
  • Methods can not be serialized.

 

How to use XmlSerializer

 

Serialization is handled through the XmlSerializer class. When constructing an instance of the XmlSerializer you must pass the typeof the class you wish to serialize.

Serialization is done with call to XmlSerializers Serialize method, and De-serialization is done with a call to the Deserialize method.

 

Basic Serialization Example

Type

// Class to Serialize

CustomerClass = class(TObject)

public

FirstName : String;

LastName : String;

end;

 

procedure Serialize;

var

Customer : CustomerClass;

XS : XmlSerializer;

SW : StringWriter;

begin

// Create an instance of CustomerClass and populate it with data

Customer := CustomerClass.Create;

Customer.FirstName := 'John';

Customer.LastName := 'Doe';

 

// Create an instance of XmlSerializer passing the CustomerClass Type

XS := XmlSerializer.Create(TypeOf(CustomerClass));

 

// Create a TextWriter Decendant to store Serialized Object

SW := StringWriter.Create;

 

// Serialize the Object to the TextWriter

XS.Serialize(SW,Customer);

// Show Serialized Object in a Message Box

MessageBox.Show(SW.ToString);

end;

 

 

Basic De-serialization Example

Type

// Class to Serialize

CustomerClass = class(TObject)

public

FirstName : String;

LastName : String;

end;

 

procedure DeSerialize(DocumentStr : String);

var

Customer : CustomerClass;

XS : XmlSerializer;

SR : StringReader;

begin

// Create an instance of XmlSerializer passing the CustomerClass Type

XS := XmlSerializer.Create(TypeOf(CustomerClass));

 

// Create a TextReader or Stream Decendant and load the serialized data into it.

SR := StringReader.Create(DocumentStr);

 

// Deserialize the TextReader/Stream Decendant and Type Cast it to CustomerClass

Customer := CustomerClass(XS.Deserialize(SR));

 

// Display a Message Box to show Customer Information

MessageBox.Show(Customer.FirstName + ' ' + Customer.LastName);

 

end;

 


Controlling Serialization through Attributes

 

There are several different attributes that can be applied to your class to control how it is serialized to Xml.

 

Example of Renaming the Xml Document Root Element and Sub Element Names

[XmlRoot(ElementName = 'customer')]

CustomerClass = class(TObject)

public

[XmlElement(ElementName = 'FNAME')]

FirstName : String;

[XmlElement(ElementName = 'LNAME')]

LastName : String;

end;

Resulting File

<?xml version="1.0" encoding="utf-16"?>

<customer xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<FNAME>John</FNAME>

<LNAME>Doe</LNAME>

</customer>

 

Example using XmlAttribute and Embeded Classes

 

[XmlRoot(ElementName = 'customer')]

CustomerClass = class(TObject)

public

type

NameClass = Class(TObject)

public

[XmlAttribute('First')]

FirstName : String;

[XmlAttribute('Last')]

LastName : String;

end;

public

[XmlElement('name')]

Name : NameClass;

end;

Resulting File

<?xml version="1.0" encoding="utf-16"?>

<customer xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<name First="John" Last="Doe" />

</customer>

 

Performing XSLT Transformations

 

The .Net Framework provides the necessary classes to perform XSLT. The XslTranform class provides all of the functionality required. There are two key methods that need to be called for every transformation. First you must call XslTransform.Load to load the stylesheet that will be used in the transformation. The second is XslTransform.Transform which will perform the transformation on a specified Xml Source. Both methods are overloaded and have many different signatures, please refer to the SDK Documentation for details on each overload.

 

Var
XDD : XmlDataDocument;
SW : StringWriter;
XT : XslTransform;

DS : DataSet;
begin
BdpDataAdapter1.Fill(DS);
XDD := XmlDataDocument.Create(DS);
SW := StringWriter.Create();
XT := XslTransform.Create;

// Load The transformation
XT.Load('C:DEMOSTRANSFORM.XSL');

// Perform Transformation
XT.Transform(XDD,nil,SW);
TextBox1.Text := SW.ToString;
end;

 

Tools

The .Net framework provides a command line utility (XSD.EXE) that is very useful for dealing with serialization and schemas.

 

XSD.EXE  The Xml Schema Definition Tool

 

The XSD tool can do the following

7        Generating Schema Documents, from one or more Xml Instance Documents

7        Creating a Serialized Class from a Schema

7        Creating a typed DataSet Class from a Schema

7        Convert a Compiled Serialized Class in an Assembly in to XSD

 

Petr Vones a repected member of the Delphi Community has created a Delphi open tool that wraps the functionality found in XSD. The Open Tool also contains several other useful XML Tools. This tool makes it easy to create Delphi versions of the Classes.

 

This tool can be downloaded here:

http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=21094

 

 

 


Appendix

 

Training Example Xml Document

 

The following is the Xml Document that is used in the examples found in the Appendix.

 

Training.xml

<?xml version=1.0 encoding=ISO-8859-1 standalone=yes?>

<training>

<class>

<name number=401> Introduction to XML</name>

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<presenter>Robert Love</presenter>

<event name=BorCon/>

</class>

<class>

<name number=402> Introduction to .NET</name>

<subject>Borland will really show you how to do .NET</subject>

<presenter>Al Borland</presenter>

<event name=BorCon/>

</class>

</training>

 

XPath

 

XPath is a syntax used to query an XML document tree. XPath gets its name due to the path notation that it uses to describe the XML tree. XPath is a critical stepping-stone if you desire to learn XSLT. It also provides a quick way you can query an XML document and get either a node set, or a single value result.

 

 

Getting Started with XPath

 

XPath uses a path like syntax. The path delimiter is /" like you would find in a Linux based system. Each node in the tree can be compared to a directory on your file system. Most of the examples in this section will be using the original training.xml document. The results of each query will display the raw XML of each of the nodes returned.

 

Say we want to get a list of presenters in our document. We can access that list by specifying the path to the presenter.

Query

 

 

/training/class/presenter

 

Result

 

 

<presenter>Robert Love</presenter>

<presenter>Al Borland</presenter>

 

 

 

Stepping back one level and returning a list of classes will not just return the class but all child elements.

 

Query

 

 

/training/class

 

Result

 

 

<class>

<name number="401">Introduction to XML</name>

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<presenter>Robert Love</presenter>

<event name="BorCon"/>

</class>

<class>

<name number="402">Introduction to .NET</name>

<subject>Borland will really show you how to do .NET</subject>

<presenter>Al Borland</presenter>

<event name="BorCon"/>

</class>

 

 

Relative Paths

 

Currently all Xpath statements we have explored have started with a single / this is considered an absolute path. If you start directly with a name such as training/class/subject it is applied to a current context node. In all of the prior examples the context has been the implied document node. When we introduce XPath predicates and XSLT you will see practical use of relative paths.

You also have an option that allows you to search for nodes with-in a document. Using // you can search for all nodes, regardless of location, that match the following.

 

If you want to see all of the nodes with name of subject this could be done with.

Query

 

 

//subject

 

Result

 

 

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<subject>Borland will really show you how to do .NET</subject>

 

 

Path Wildcards

 

You can also use * as a wildcard inside of your path.

 

The following example uses the wild card twice. It will return all subject nodes that are in the 3rd tree level.

Query

 

 

/*/*/subject

 

Result

 

 

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<subject>Borland will really show you how to do .NET</subject>

 

 


Current and Prior Node

Just like paths you can use . and .. to represent the current and prior nodes.

The following example shows how to use . to get the current node.

Although this example is not very practical, it is only meant to introduce you to the fact that . can be used.

Query

 

/training/*/.

Result

 

<class>

<name number="401">Introduction to XML</name>

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<presenter>Robert Love</presenter>

<event name="BorCon"/>

</class>

<class>

<name number="402">Introduction to .NET</name>

<subject>Borland will really show you how to do .NET</subject>

<presenter>Al Borland</presenter>

<event name="BorCon"/>

</class>

 

The following example shows how to use .. to get the previous node.

Although this example is not very practical, it is only meant to introduce you to the fact that .. can be used.

Query

 

/training/*/..

Result

 

<training>

<class>

<name number="401">Introduction to XML</name>

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<presenter>Robert Love</presenter>

<event name="BorCon"/>

</class>

<class>

<name number="402">Introduction to .NET</name>

<subject>Borland will really show you how to do .NET</subject>

<presenter>Al Borland</presenter>

<event name="BorCon"/>

</class>

</training>

 


 

 

XPath Axes

 

Current and Prior nodes can also be obtained through an axis type statement. An axis allows you to specify what the current node will query. To specify an axis, the location path is prefixed with the axis.

 

 

This can be done with the following syntax:

 

axis::path

 

Following shows two ways to get current and prior nodes.

Axis Syntax

. and .. Syntax

/training/*/self::*

/training/*/.

/training/*/parent::*

/training/*/..

 

So basically . is a shortcut for the self axis, and .. is a shortcut for the parent axis.

 

There are several other axes that you can use in an XPath statement.

Axis

Description

Many descriptions taken directly from the XPath Specification

Self

Identifies the context node.

Child

Contains the children of the context node

This is the default axis. If you dont specify an axis child is implied.

Parent

Contains the parent of the context node if there is one.

descendant

Contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus the descendant axis never contains attribute or namespace nodes.

descendant-or-self

Contains the context node and the descendants of the context node.

Ancestor

Contains the ancestors of the context node; the ancestors of the context node consist of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always include the root node, unless the context node is the root node.

Ancestor-or-self

Contains all nodes in the same document as the context node that are after the context node in document order, excluding any descendants and excluding attribute nodes and namespace nodes.

following

Contains all nodes in the same document as the context node that are after the context node in document order, excluding any descendants and excluding attribute nodes and namespace nodes.

following-sibling

Contains all the following siblings of the context node; if the context node is an attribute node or namespace node.

preceding

Contains all nodes in the same document as the context node that are before the context node in document order, excluding any ancestors and excluding attribute nodes and namespace nodes.

preceding-sibling

Contains all the preceding siblings of the context node; if the context node is an attribute node or namespace node, the preceding-sibling axis is empty.

attribute

Contains the attributes of the context node; the axis will be empty unless the context node is an element.

namespace

Contains the namespace nodes of the context node; the axis will be empty unless the context node is an element.

 

 

XPath Predicates

 

The path statement will only take you so far. Sometimes you need to select which part of the list you are looking for. Using the [] you can include a statement to limit the result set, this is called Predicate.

 

In the query below we look at the presenter name and only return the class that matches that presenters name.

Query

 

 

/training/class[presenter="Robert Love"]

 

Result

 

 

<class>

<name number="401">Introduction to XML</name>

<subject>XML, DTD, XSD, DOM, XPATH, and XSLT.</subject>

<presenter>Robert Love</presenter>

<event name="BorCon"/>

</class>

 

 


Accessing Attributes

To access an attribute you must prefixing its name with a @.

 

In the following example, we are requesting a list of classes where number attribute is the value of 402.

Query