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 |
---|---|
BuildSqlFromXmlNodes method |
|
BuildSqlFromXmlNodes method |
|
Source property |
|
Context property |
|
CreateNavigator method |
|
GetNamedNodeProperty method |
|
SetNamedNodeProperty method |
|
Execute method |
|
Execute method |
|
Execute method |
|
Site property |
|
Add methods |
|
Manifest property |
|
Xml property |
|
Execute method |
|
SignatureBlockXmlNode property |
|
SignatureContainer property |
|
GetContextNodes methods |
|
SelectNodes methods |
|
SelectText methods |
|
Execute method |
|
GenerateDataSetDiffGram method |
|
OldParent property |
|
Site property |
|
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 |
|
NewFromFormTemplate method |
|
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 |
---|---|
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:
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).
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.
The repeatingTableRow1 object variable is passed to the SelectNodes method of the View class to select the nodes in that row.
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.
The Count property of the XPathNodeIterator class is used to display the number of nodes contained in the selectedNodes object variable.
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.