How to: Work with the XPathNavigator and XPathNodeIterator Classes

Applies to: InfoPath 2010 | InfoPath Forms Services | Office 2010 | SharePoint Server 2010 | Visual Studio | Visual Studio Tools for Microsoft Office

In this article
Using the XPathNavigator Class to Access the Main Data Source of the Form
Selecting and Setting the XML Nodes for Fields in the Main Data Source
Using the XPathNavigator Class to Access an External Data Source
InfoPath Object Model Members That Use the XPathNavigator and XPathNodeIterator Classes
Using the XPathNavigator and XPathNodeIterator Classes to Work with Data Selected in a View

To access and manipulate the XML data in form template data sources, many members of the managed code object model provided by the Microsoft.Office.InfoPath namespace either create or can be passed an instance of the XPathNavigator class of the System.Xml.XPath namespace. After you have access to an XPathNavigator object returned by an InfoPath object model member, you can use the properties and methods of the XPathNavigator class to work with the data.

The most frequently used member of the Microsoft.Office.InfoPath namespace that uses the XPathNavigator class is the CreateNavigator method of the DataSource class, which enables you to work with the stored data represented by a DataSource object. The CreateNavigator method creates an XPathNavigator object positioned at the root of the data source represented by the DataSource object.

Tip

If you are familiar with using MSXML5 from script to work with data in Microsoft InfoPath 2003, you can think of the CreateNavigator method as the replacement for the DOM property of the DataObject.

Using the XPathNavigator Class to Access the Main Data Source of the Form

To access the main data source of the form, call the CreateNavigator method directly from the this (C#) or Me (Visual Basic) keyword. The following example creates an XPathNavigator object positioned at the root of the main data source by using the CreateNavigator method, and then uses the OuterXml property of the XPathNavigator class to display the XML returned in a message box.

XPathNavigator myNavigator = 
   this.CreateNavigator();
MessageBox.Show("Main data source XML: " +
   myNavigator.OuterXml.ToString());
Dim myNavigator As XPathNavigator  = _
   Me.CreateNavigator()
MessageBox.Show("Main data source XML: " & _
   myNavigator.OuterXml.ToString())

Note

Calling the CreateNavigator method directly from the this or Me keyword is equivalent to calling CreateNavigator method by using the MainDataSource property (this.MainDataSource.CreateNavigator()) or by passing an empty string to the DataSources property of the XmlForm class (this.DataSources[""].CreateNavigator()).

Selecting and Setting the XML Nodes for Fields in the Main Data Source

To select the single XML node for a field in a data source, use the SelectSingleNode(String,IXmlNamespaceResolver) method of the XPathNavigator class. If you want to work with a set of repeating fields or repeating groups, use the Select(String,IXmlNamespaceResolver) method of the XPathNavigator class. This method returns an XPathNodeIterator object that represents a collection of nodes.

Selecting and Setting the Value of a Single Node

The overloaded SelectSingleNode method that you must use has an xpath parameter that takes an XPath expression as a string, and a resolver parameter that takes an XmlNamespaceManager object for resolving namespace prefixes. To select a single node in the form's main data source, pass in an XPath expression that specifies the field or group that you want to select for the xpath parameter, together with the XmlNamespaceManager object that is returned by the NamespaceManager property of the XmlForm object. The returned XmlNamespaceManager object is initialized at load time with all the namespaces that are defined by the form template's form definition file (.xsf).

Tip

The easiest way to create an XPath expression for selecting a node in the form's data source is to right-click the field or group in the Fields task pane, and then click Copy XPath. To create and test hand-edited XPath expressions for accessing nodes in a complex or heavily nested XML schema, add an Expression Box control to the form, specify the XPath expression for the control, and then preview the form to display the results.

The following example uses the SelectSingleNode method to select the single node for the EmailAlias field. Then it uses the SetValue method of the XPathNavigator class and the UserName property of the User class to set the value of the field to the current user's alias.

XPathNavigator emailAlias = 
   this.CreateNavigator().SelectSingleNode(
      "/my:myFields/my:EmailAlias", NamespaceManager);
emailAlias.SetValue(this.Application.User.UserName.ToString());
Dim emailAlias As XPathNavigator = _
   Me.CreateNavigator().SelectSingleNode( _
      "/my:myFields/my:EmailAlias", NamespaceManager)
emailAlias.SetValue(Me.Application.User.UserName.ToString())

For information about how to create XPath expressions, see the XPath Reference on MSDN, and the XML Path Language (XPath) Version 1.0 W3C Recommendation.

Setting the Value of a Node That Has the xsi:nil Attribute

For certain data types, trying to set the value of a blank field programmatically raises the error "Schema validation found non-data type errors." Typically the cause of this error is that the element has the xsi:nil attribute set to true. If you examine the underlying XML element for the blank field in the form, you can see this setting. For example, the XML fragment for the following blank Date field has the xsi:nil attribute set to true.

<my:myDate xsi:nil="true"></my:myDate>

If the xsi:nil attribute is set to true, it indicates that the element is present but has no value, or in other words, is null . If you try to programmatically set the value of such a node, InfoPath displays the "Schema validation found non-data type errors" message because the element is currently flagged as being null . InfoPath sets the xsi:nil attribute to true for null fields of the following data types:

  • Whole Number (integer)

  • Decimal (double)

  • Date (date)

  • Time (time)

  • Date and Time (dateTime)

To prevent this error, your code must test for the xsi:nil attribute, and if it is present, remove it before setting the value of the node. The following subroutine takes an XpathNavigator object positioned on the node that you want to set, checks for the nil attribute, and then deletes it, if it exists.

public void DeleteNil(XPathNavigator node)
{
   if (node.MoveToAttribute(
      "nil", "http://www.w3.org/2001/XMLSchema-instance"))
      node.DeleteSelf();
}
Public Sub DeleteNil(ByVal node As XPathNavigator)
   If (node.MoveToAttribute( _
      "nil", "http://www.w3.org/2001/XMLSchema-instance")) Then
      node.DeleteSelf()
   End If
End Sub

You can call this subroutine before you try to set a field of a data type that might have the xsi:nil attribute, as shown in the following example that sets a Date field.

// Access the main data source.
XPathNavigator myForm = this.CreateNavigator();

// Select the field.
XPathNavigator myDate = myForm.SelectSingleNode("/my:myFields/my:myDate", NamespaceManager);

// Check for and remove the "nil" attribute.
DeleteNil(myDate);

// Build the current date in the proper format. (yyyy-mm-dd)
string curDate = DateTime.Today.Year + "-" + DateTime.Today.Month + 
   "-" + DateTime.Today.Day;

// Set the value of the myDate field.
myDate.SetValue(strCurDate);
' Access the main data source.
Dim myForm As XPathNavigator = Me.CreateNavigator()

' Select the field.
Dim myDate As XPathNavigator = _
   myForm.SelectSingleNode("/my:myFields/my:myDate", NamespaceManager)

' Check for and remove the "nil" attribute.
DeleteNil(myDate)

' Build the current date in the proper format. (yyyy-mm-dd)
Dim curDate As String = DateTime.Today.Year + "-" + _
   DateTime.Today.Month + "-" + DateTime.Today.Day

' Set the value of the myDate field.
myDate.SetValue(strCurDate)

Note

Although the implementation of the XPathNavigator object in InfoPath exposes the SetTypedValue method—which is used to set a node using a value of a specific type—InfoPath does not implement that method. You must use the SetValue method instead, and pass a string value of the correct format for the data type of the node.

Selecting and Setting a Set of Repeating Nodes

To specify a set of repeating fields or groups that are of an indeterminate number, use the Select method of the XPathNavigator class. This method returns an XPathNodeIterator object that you can use to iterate over the specified collection of nodes.

The following example assumes that your form template contains a Bulleted List or similar repeating control that is bound to a repeating element named field1. The XPath of the field is passed to the Select method, and the returned XPathNodeIterator is assigned to the nodes variable. You use the MoveNext method to iterate over the collection of nodes, and the Current property to return an XPathNavigator object positioned on the current node. Finally, you use the Value property to retrieve and display the value of each repeating field.

string message = String.Empty;
XPathNavigator root = this.CreateNavigator();
XPathNodeIterator nodes = 
   root.Select("/my:myFields/my:group1/my:field1", NamespaceManager);

while (nodes.MoveNext())
{
    message += nodes.Current.Value + System.Environment.NewLine;
}
MessageBox.Show(message);
Dim message As String = String.Empty
Dim root As XPathNavigator = Me.CreateNavigator()
Dim nodes As XPathNodeIterator = _
   root.Select("/my:myFields/my:group1/my:field1", NamespaceManager)

Do While nodes.MoveNext
    message += nodes.Current.Value & System.Environment.NewLine
Loop

MessageBox.Show(message)

The previous example works with string values in the specified repeating field. However, if the field contains numeric values, you can use similar code to iterate over the values in the field to perform arithmetic, such as calculating the total or average of the values.

Similarly, instead of using the Value property to retrieve the value of each instance of the repeating field, you can use the SetValue method to iterate over the fields and set their values, as shown in the following example.

XPathNavigator root = this.CreateNavigator();
XPathNodeIterator nodes = 
   root.Select("/my:myFields/my:group1/my:field1", NamespaceManager);
int myInt = 1;
while (nodes.MoveNext())
{
   nodes.Current.SetValue(myInt.ToString());
   myInt = myInt + 1;
}
Dim root As XPathNavigator = Me.CreateNavigator()
Dim nodes As XPathNodeIterator = _
   root.Select("/my:myFields/my:group1/my:field1", NamespaceManager)
Dim myInt As Integer = 1
Do While nodes.MoveNext
   nodes.Current.SetValue(myInt.ToString())
   myInt = myInt + 1
Loop

Using the XPathNavigator Class to Access an External Data Source

To access an external data source associated with the form, pass the name of the data source to the DataSources property of the XmlForm class. To create a connection to a new external data source, or to view a list of the names of existing external data source connections, click Data Connections on the Data tab of the ribbon.

The following code sample shows how to create an XPathNavigator object positioned at the root of an external data source named "CityList" by using the CreateNavigator method, and then uses the OuterXml property of the XPathNavigator class to display the XML returned in a message box. This code sample assumes that you created a data connection to a list of city names that are stored in an external data source, such as an XML document or a SharePoint list, and named that data connection "CityList."

XPathNavigator myNavigator = 
   this.DataSources["CityList"].CreateNavigator();
MessageBox.Show("External data source XML: " + 
   myNavigator.OuterXml.ToString());
Dim myNavigator As XPathNavigator  = _
   Me.DataSources("CityList").CreateNavigator()
MessageBox.Show("External data source XML: " & _
   myNavigator.OuterXml.ToString())

After you have access to an XPathNavigator object positioned at the root of an external data source, you can use members of the XPathNavigator class such as the SelectSingleNode and SetValue methods to work with the data it contains.

InfoPath Object Model Members That Use the XPathNavigator and XPathNodeIterator Classes

The following table provides a summary of all of the members of the Microsoft.Office.InfoPath namespace that use the XPathNavigator class to access, manipulate, or submit XML data.

Parent Class

Member

AdoQueryConnection

BuildSqlFromXmlNodes method

AdoSubmitConnection

BuildSqlFromXmlNodes method

ClickedEventArgs

Source property

ContextChangedEventArgs

Context property

DataSource

CreateNavigator method

GetNamedNodeProperty method

SetNamedNodeProperty method

EmailSubmitConnection

Execute method

FileQueryConnection

Execute method

FileSubmitConnection

Execute method

FormError

Site property

FormErrorCollection

Add methods

FormTemplate

Manifest property

MergeEventArgs

Xml property

SharepointListQueryConnection

Execute method

Signature

SignatureBlockXmlNode property

SignedDataBlock

SignatureContainer property

View

GetContextNodes methods

SelectNodes methods

SelectText methods

WebServiceConnection

Execute method

GenerateDataSetDiffGram method

XmlEventArgs

OldParent property

Site property

XmlForm

MainDataSource property, which returns a DataSource object that in turn provides the CreateNavigator method for creating an XPathNavigator object positioned at the root of the form's underlying XML document (main data source).

MergeForm method

XmlFormCollection

NewFromFormTemplate method

XmlValidatingEventArgs

ReportError methods

In addition to the InfoPath object model members that return or accept an XPathNavigator object, the following methods return an instance of the XPathNodeIterator class of the System.Xml.XPath namespace for iterating over the XML nodes of items that are specified or selected in a view.

Parent Class

Member

View

GetContextNodes methods

GetSelectedNodes method

Using the XPathNavigator and XPathNodeIterator Classes to Work with Data Selected in a View

The following example uses members of both the XPathNavigator and XPathNodeIterator classes to work with form data in the following sequence:

  1. The CreateNavigator method of the DataSource class is used to create an XPathNavigator object variable named repeatingTableRow1, which by default is positioned at the root of the underlying XML document of the form (the main data source).

  2. The SelectSingleNode method of the XPathNavigator class is used to move the position of the XPathNavigator object to the first row of a Repeating Table control bound to group2 in the data source.

  3. The repeatingTableRow1 object variable is passed to the SelectNodes method of the View class to select the nodes in that row.

  4. An XPathNodeIterator object variable named selectedNodes is declared and the GetSelectedNodes method of the View class is used populate the XPathNodeIterator object with the selected nodes.

  5. The Count property of the XPathNodeIterator class is used to display the number of nodes contained in the selectedNodes object variable.

  6. A For/Each loop is used to iterate over the nodes in the selectedNodes object variable and display information about each node using the Name, InnerXml, and Value properties of the XPathNavigator class.

// Create XPathNavigator and specify XPath for nodes.
XPathNavigator repeatingTableRow1 = 
   this.CreateNavigator().SelectSingleNode(
   "/my:myFields/my:group1/my:group2[1]", NamespaceManager);

// Select nodes in specified XPathNavigator.
CurrentView.SelectNodes(repeatingTableRow1);

// Get selected nodes.
XPathNodeIterator selectedNodes = 
   CurrentView.GetSelectedNodes();

// Display the count of selected nodes.
MessageBox.Show(selectedNodes.Count.ToString());

// Loop through collection and display information.
foreach (XPathNavigator selectedNode in selectedNodes)
{
   MessageBox.Show(selectedNode.Name);
   MessageBox.Show(selectedNode.InnerXml);
   MessageBox.Show(selectedNode.Value);
}
' Create XPathNavigator and specify XPath for nodes.
Dim repeatingTableRow1 As XPathNavigator  = _
   Me.CreateNavigator().SelectSingleNode( _
   "/my:myFields/my:group1/my:group2[1]", NamespaceManager)

' Select nodes in specified XPathNavigator.
CurrentView.SelectNodes(repeatingTableRow1)

' Get selected nodes.
Dim selectedNodes As XPathNodeIterator = _
   CurrentView.GetSelectedNodes()

' Display the count of selected nodes.
MessageBox.Show(selectedNodes.Count.ToString())

' Loop through collection and display information.
Dim selectedNode As XPathNavigator
For Each selectedNode In selectedNodes
   MessageBox.Show(selectedNode.Name)
   MessageBox.Show(selectedNode.InnerXml)
   MessageBox.Show(selectedNode.Value)
Next

For more information about how to work with XML data from InfoPath form templates, see Working with XML Data Using the XPathNavigator Class in InfoPath 2007 Form Templates.