Export (0) Print
Expand All
23 out of 25 rated this helpful - Rate this topic

Working with XML Data Using the XPathNavigator Class in InfoPath 2007 Form Templates

Office 2007

Summary: Learn how to use the XPathNavigator and XPathNodeIterator classes to access and work with data in business logic written with managed code in Microsoft Office InfoPath 2007 form templates. (18 printed pages)

Mark Roberts, Microsoft Corporation

June 2007

Applies to: Microsoft Office InfoPath 2007, InfoPath Forms Services 2007

Contents

Overview of the XPathNavigator and XPathNodeIterator Classes

One of the main design principles for Microsoft Office InfoPath 2007 and InfoPath Forms Services 2007 is that you can create your form template once, write code for it once, build and publish it once (to a server running InfoPath Forms Services, such as Microsoft Office Forms Server 2007 and Microsoft Office SharePoint Server 2007), and then have it work in both the browser and InfoPath 2007. The InfoPath product team refers to this design principle as "design once." To make "design once" easier for form templates that contain business logic code, a new managed code object model was created. It is provided by the types and members of the Microsoft.Office.InfoPath namespace.

To support the ability to access and manipulate the XML data in form template data sources regardless of whether the form template is open in InfoPath or in the browser, many InfoPath managed code object model members either create, or can be passed, an instance of the XPathNavigator class of the System.Xml.XPath namespace. Additionally, some object model members return an XPathNodeIterator that enables you to iterate over a collection of XML nodes.

After you have access to an XPathNavigator object or an XPathNodeIterator object returned by an InfoPath object model member, you can use the properties and methods of these classes to work with the form's data and secondary data sources.

For a complete listing of the classes and members in the Microsoft.Office.InfoPath namespace that can use the XPathNavigator and XPathNodeIterator classes, see the Appendix: InfoPath Object Model Members That Work with XPathNavigator and XPathNodeIterator section in this article.

This article provides examples of how to work with XML data using the XPathNavigator and XPathNodeIterator objects from managed code in InfoPath 2007 form templates.

Accessing a Data Source Using the CreateNavigator Method

One commonly used member of the Microsoft.Office.InfoPath namespace that uses the XPathNavigator class is the CreateNavigator method of the DataSource class. The CreateNavigator method creates an XPathNavigator object positioned at the root of the data source represented by the specified DataSource object. You can use the CreateNavigator method to access the main data source, which is the underlying XML document of the form. You can also access any secondary data sources that are defined using the Data Connections command on the Tools menu, such as a separate XML document, database, Web service, or SharePoint list.

Accessing the Main Data Source

The MainDataSource property of the XmlForm class gets a reference to a DataSource object that represents the underlying XML document of the form. You can then use the CreateNavigator method of the DataSource object to create an XPathNavigator object to work with the underlying XML data in the form.

In InfoPath 2007, you can access the XmlForm object for the current form by using the this keyword (C#) or the Me keyword (Visual Basic). The following example uses the MainDataSource property to access the DataSource object that represents the underlying XML document of the form. It then uses the CreateNavigator method to create an XPathNavigator object positioned at the root of the data source. This XPathNavigator object is assigned to the myNavigator variable, and the OuterXml property of the XPathNavigator class is used to display the XML of the main data source in a message box.

XPathNavigator myNavigator = 
   this.MainDataSource.CreateNavigator();
MessageBox.Show(
   myNavigator.OuterXml.ToString(),"Main Data Source XML");
Bb509311.note(en-us,office.12).gifNote:

InfoPath does not require that you use the this keyword (C#) or the Me keyword (Visual Basic) to access members of the XmlForm object for the current form. You can omit them from your code.

Accessing a Secondary Data Source

The following example assumes that you used the Data Connections command to create a secondary data source that contains a list of city names and named it "CityList." The kind of data source that you are connecting to is not necessarily important. The important detail is that you are accessing the data source by referencing the name—in this case, "CityList"—from the DataSourceCollection object returned by the DataSources property of the XmlForm object for the current form. After the XPathNavigator object is created for the "CityList" data source using the CreateNavigator method, it is assigned to the myNavigator variable, and the OuterXml property of the XPathNavigator class is used to display the XML of the data source in a message box.

XPathNavigator myNavigator = 
   this.DataSources["CityList"].CreateNavigator();
MessageBox.Show(
   myNavigator.OuterXml.ToString(),"Secondary Data Source XML");

Selecting XML Nodes

To select a single node 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 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 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 xmlns attributes in the xDocumentClass element of the form template's form definition file (.xsf).

Bb509311.Tip(en-us,office.12).gifTip:

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 Data Source task pane, and then click Copy XPath. To create and test more complex manually edited XPath expressions, 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 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.MainDataSource.CreateNavigator().SelectSingleNode(
      "/my:myFields/my:EmailAlias", NamespaceManager);
emailAlias.SetValue(this.Application.User.UserName.ToString());

For information about creating 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 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();
}

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 = MainDataSource.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);
Bb509311.note(en-us,office.12).gifNote:

Although the implementation of the XPathNavigator object in InfoPath 2007 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 = MainDataSource.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);

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 = MainDataSource.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;
}

Deleting Multiple Nodes

If you know the range of a set of fields or groups that you want to delete, you can create two XPathNavigator objects positioned on the first and last nodes in the range. To specify each node, use the one-based ordinal position of the nodes in the XPath expression that you pass to the SelectSingleNode method as a predicate enclosed in brackets ([]). Then use the DeleteRange method of the XPathNavigator class to delete the range of nodes.

The following example deletes the nodes for the second, third, and fourth fields in the specified group.

XPathNavigator root = MainDataSource.CreateNavigator();
XPathNavigator first = 
   root.SelectSingleNode("/my:myFields/my:group1/my:field1[2]",
   NamespaceManager);
XPathNavigator last = 
   root.SelectSingleNode("/my:myFields/my:group1/my:field1[4]",
   NamespaceManager);
first.DeleteRange(last);

If you want to delete all the fields in a group, but you do not know the ordinal value of the node for the last field, you can use the XPath position function and the last function in the predicate for selecting the last node to pass to the DeleteRange method, as shown in the following example.

string myGroup = "/my:myFields/my:group1/my:field1";
XPathNavigator root = MainDataSource.CreateNavigator();
XPathNavigator first = root.SelectSingleNode( 
   myGroup + "[1]", NamespaceManager);
XPathNavigator last = root.SelectSingleNode(myGroup + 
   "[position()=last()]", NamespaceManager);
first.DeleteRange(last);

Working with the Current Node

When a user adds or changes data in the form's underlying XML document, InfoPath raises one of the events defined by the XmlEvent class. For example, the Changed event for a field occurs after a change to the field has been validated and accepted. You typically use this event to change some other data in the form, or to perform calculations after the change to the current field or group has occurred. When the Changed event is raised, InfoPath passes an XmlEventArgs object to the handler for the event that provides properties for working with the node you want to change.

The next example uses the Site property of the XmlEventArgs object, which returns an XPathNavigator object positioned at the node that raised the event. The example assumes a form template with a Repeating Table control. The control contains two columns that are bound to the SelectCustomer field and the CustomerName field of the form's main data source. The SelectCustomer field is bound to a Drop-Down List Box control that looks up the CustomerID value from a Customers element in an external data source named "Customers."

In the example, the data source is an XML file named "Customers.xml" that you add to the form template by using the Resource Files command on the Tools menu. You then specify it as a data source by using the Data Connections command. However, you can also retrieve the data from another kind of secondary data source, such as a SharePoint list or SQL Server database. The Customers.xml file is structured as shown in the following XML fragment.

<?xml version="1.0" encoding="UTF-8"?>
<Customers>
   <Customer>
      <CustomerID>ALFKI</CustomerID>
      <CompanyName>Alfreds Futterkiste</CompanyName>
      <ContactName>Maria Anderss</ContactName>
      <ContactTitle>Sales Representative</ContactTitle>
      <Address>Obere Str. 57</Address>
      <City>Berlin</City>
      <PostalCode>12209</PostalCode>
      <Country>Germany</Country>
      <Phone>030-0074321</Phone>
      <Fax>030-0076545</Fax>
   </Customer>
   <Customer>
      <CustomerID>ANATR</CustomerID>
      <CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
      <ContactName>Ana Trujillo</ContactName>
      <ContactTitle>Owner</ContactTitle>
      <Address>Avda. de la Constitución 2222</Address>
      <City>México D.F.</City>
      <PostalCode>05021</PostalCode>
      <Country>Mexico</Country>
      <Phone>(5) 555-4729</Phone>
      <Fax>(5) 555-3745</Fax>
   </Customer>
   ...
</Customers>

In the Properties dialog box of the Drop-Down List Box control, you specify that the list box entries are looked up from the CustomerID element of the Customers data source. To add the event handler to the SelectCustomer field for the Changed event, right-click the control that is bound to the field, point to Programming, and then click Changed Event.

Figure 1 shows the Drop-Down List Box control that is bound to the SelectCustomer field. It displays data from the CustomerID element of the Customers.xml secondary data source.

Figure 1. Drop-Down List Box control bound to SelectCustomer field

Drop-Down List Box control bound to SelectCustomer

The code in the following example shows the event handler for the Changed event of the SelectCustomer field. The event handler performs the following operations when a user selects a value from the Drop-Down List Box bound to the field:

  1. Creates an XPathNavigator positioned at the root of the "Customers" secondary data source.

  2. Creates an XPathNavigator positioned on the SelectCustomer field in the main data source by using the Site property.

  3. Uses the MoveToParent method of the XPathNavigator class to enable access to its sibling, the CustomerName field, in the current row of the Repeating Table control.

  4. Checks whether the user selected the blank value at the top of the Drop-Down List Box after previously selecting a CustomerID value, and if so, clears the value from the CustomerName field.

  5. Gets the company name from the CompanyName element contained within a Customer element in Customers.xml file using an XPath expression that matches the CustomerID field that is selected in the Drop-Down List Box control.

  6. Selects the CustomerName field from the parent node (the current row in the Repeating Table control) and sets its value to the value that is retrieved from the matching CompanyName element.

public void SelectCustomer_Changed(object sender, XmlEventArgs e)
{
   try
   {
      // Get a reference to the Customers secondary data source, 
      // and create an XPathNavigator object for it.
      XPathNavigator Customers = 
         this.DataSources["Customers"].CreateNavigator();

      // Create an XPathNavigator object positioned on the current
      // "site", which is the SelectCustomer node in the 
      // main data source.
        XPathNavigator myForm = e.Site.CreateNavigator();

      // Move to the parent of the SelectCustomer node,
      // so that the code can access the CustomerName node.
        myForm.MoveToParent();

      // Check if the user selected the blank value from the 
      // Drop-Down List Box after previously selecting a CustomerID.
      if (e.Site.InnerXml == "")
      {
         // Clear previously selected value from CustomerName field.
         myForm.SelectSingleNode("my:CustomerName", 
            this.NamespaceManager).DeleteSelf();
      }
      else
      {
         // Get the Company name from the Customers data source 
         // using the value in the CustomerID node.
         string custName = Customers.SelectSingleNode(
            "/Customers/Customer[CustomerID = '" + e.Site.InnerXml + 
            "']/CompanyName", this.NamespaceManager).InnerXml;

         // Select the CustomerName node from the current row and 
         // set its value.
         myForm.SelectSingleNode("my:CustomerName",
            this.NamespaceManager).SetValue(custName);
      }
   }
   catch (Exception ex)
   {
      MessageBox.Show("Error: " + ex.Message);
   }
}

Working with Nodes Using Methods of the View Class

In addition to working directly with the data sources of the form, as shown in the previous examples, the View class provides methods for working with data based on the controls in the current view. For example, you can work with nodes based on a user's current selection within a control, or across one or more controls. Most of these methods also accept or return XPathNavigator or XPathNodeIterator objects.

Bb509311.note(en-us,office.12).gifNote:

You cannot use the GetContextNodes and GetSelectedNodes methods from a Button control on the form because when the user clicks the Button, the focus is moved away from the control or controls that contain the data you want to work with. But you can write functions using these methods that you can call from a custom task pane, menu command, or toolbar.

Table 1 provides a list of View class methods that you can use to work with data that is bound to controls on the form.

Table 1. View class methods for working with data

Method Description

ExecuteAction (overloaded)

Executes an editing command against a form's underlying XML document based on the current selection or view context.

GetContextNodes (overloaded)

Gets a reference to an XPathNodeIterator object for iterating over nodes based on the current context.

GetSelectedNodes

Gets a reference to an XPathNodeIterator object for iterating over all XML nodes in the current selection of items in a view.

SelectNodes (overloaded)

Selects a range of nodes in a view.

SelectText (overloaded)

Selects the text contained in an editable control that is bound to the specified node.

Conclusion

Many of the classes and members of the InfoPath managed code object model provided by the Microsoft.Office.InfoPath namespace use the XPathNavigator and XPathNodeIterator classes and their members to work with a form template's data sources. This article has provided an introduction to how to work with some members of these classes to access data in a form's underlying XML document (its main data source) and secondary data sources.

For more information about working with the XPathNavigator and XPathNodeIterator classes, see the topics in the Process XML Data Using the XPath Data Model section of the .NET Framework Developer's Guide. For more information about working with the classes and members of the Microsoft.Office.InfoPath namespace, see the InfoPath Developer Reference for Managed Code.

Additional Resources

Appendix: InfoPath Object Model Members That Work with XPathNavigator and XPathNodeIterator

The following table provides a summary of all the members in 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

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.