使用 XPathNavigator 和 XPathNodeIterator 类

为了访问和操作表单模板数据源中的 XML 数据,可以让 Microsoft.Office.InfoPath 命名空间提供的许多托管代码对象模型成员创建 System.Xml.XPath 命名空间的 XPathNavigator 类的一个实例,或者可以向它们传递一个这样的实例。 在您具有 InfoPath 对象模型成员所返回的 XPathNavigator 对象的访问权限后,可以使用 XPathNavigator 类的属性和方法处理数据。

使用 XPathNavigator 类的 Microsoft.Office.InfoPath 命名空间的最常用的成员是 DataSource 类的 CreateNavigator 方法,您可以通过该方法处理 DataSource 对象代表的存储数据。 CreateNavigator 方法创建一个 XPathNavigator 对象,该对象位于 DataSource 对象代表的数据源的根节点处。

提示

如果您熟悉在脚本中使用 MSXML5 处理 Microsoft InfoPath 2003 中的数据,就可以将 CreateNavigator 方法视为 DataObjectDOM 属性的替代者。

使用 XPathNavigator 类访问表单的主数据源

若要访问表单的主数据源,请直接通过 this (C#) 或 Me (Visual Basic) 关键字调用 CreateNavigator 方法。 下面的示例使用 CreateNavigator 方法创建一个位于主数据源的根节点处的 XPathNavigator 对象,然后使用 XPathNavigator 类的 OuterXml 属性,在一个消息框中显示返回的 XML。

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())

注意

直接从 thisMe 关键字 (keyword) 调用 CreateNavigator 方法等效于使用 MainDataSource 属性 ( this.MainDataSource.CreateNavigator()) 或通过将空字符串传递到 XmlForm 类的 DataSources 属性 ( this.DataSources[""].CreateNavigator()) 调用 CreateNavigator 方法。

选择和设置主数据源中的域的 XML 节点

若要选择数据源中的某个域的单一 XML 节点,请使用 XPathNavigator 类的 SelectSingleNode(String,IXmlNamespaceResolver) 方法。 若要处理一组重复域或重复组,请使用 XPathNavigator 类的 Select(String,IXmlNamespaceResolver) 方法。 此方法返回一个表示节点集合的 XPathNodeIterator 对象。

选择和设置单一节点的值

必须使用的重载 SelectSingleNode 方法具有采用 XPath 表达式作为字符串的 xpath 参数,以及采用 XmlNamespaceManager 对象来解析命名空间前缀的解析程序参数。 若要在窗体的main数据源中选择单个节点,请传入一个 XPath 表达式,该表达式指定要为 xpath 参数选择的字段或组,以及 XmlForm 对象的 NamespaceManager 属性返回的 XmlNamespaceManager 对象。 返回的 XmlNamespaceManager 对象在加载时通过表单模板的表单定义文件 (.xsf) 所定义的所有命名空间进行初始化。

提示

创建用于在表单数据源中选择节点的 XPath 表达式的最简单方法是右键单击“字段”任务窗格中的字段或组,然后单击“复制 XPath”。 若要创建和测试用于访问复杂或嵌套很深的 XML 架构中的节点的手动编辑的 XPath 表达式,请向表单添加“表达式框”控件,指定控件的 XPath 表达式,然后预览表单以显示结果。

以下示例使用 SelectSingleNode 方法为 EmailAlias 字段选择单个节点。 然后,它使用 XPathNavigator 类的 SetValue 方法和 User 类的 UserName 属性将该域的值设置为当前用户的别名。

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())

有关如何创建 XPath 表达式的信息,请参阅 MSDN 上的 XPath 参考和 XML Path 语言 (XPath) 版本 1.0 W3C 建议

设置具有 xsi:nil 属性的节点的值

对于某些数据类型,尝试以编程方式设置空白字段的值会引发错误“架构验证发现非数据类型错误”。通常,此错误的原因是元素的 xsi:nil 属性设置为 true。 如果您检查表单中空白域的基础 XML 元素,您会看到此设置。 例如,以下空白日期域的 XML 段的 xsi:nil 属性设置为 true

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

如果 xsi:nil 属性设置为 true,则表示相应元素存在但没有值,或者换句话说就是元素为 null。 如果您尝试以编程方式设置这样一个节点的值,InfoPath 将显示"架构验证过程发现非数据类型错误"消息,原因是元素当前标记为 null。 InfoPath 将以下数据类型的 null 域的 xsi:nil 属性设置为 true

  • Whole Number (integer)

  • Decimal (double)

  • Date (date)

  • Time (time)

  • Date and Time (dateTime)

若要防止此错误,代码必须测试 xsi:nil 属性,如果存在,请在设置节点的值之前将其删除。 以下子例程采用位于要设置的节点上的 XpathNavigator 对象,检查 nil 属性,然后删除它(如果存在)。

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

在尝试设置可能具有 xsi:nil 属性的某数据类型的域之前,您可以调用此子例程,如以下设置日期域的示例所示。

// 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)

注意

[!注释] 尽管 InfoPath 中的 XPathNavigator 对象实现可公开 SetTypedValue 方法(用于设置使用特定类型值的节点),但是 InfoPath 不会实现该方法。 您必须改用 SetValue 方法,并为节点的数据类型传递一个正确格式的字符串值。

选择和设置一组重复节点

若要指定一组为不确定数字的重复字段或组,请使用 XPathNavigator 类的 Select 方法。 此方法会返回一个 XPathNodeIterator 对象,你可以使用该对象迭代指定的节点集合。

以下示例假定表单模板包含项目 符号列表 或类似的重复控件,该控件绑定到名为 的 field1重复元素。 字段的 XPath 将传递给 Select 方法,并将返回的 XPathNodeIterator 分配给 nodes 变量。 使用 MoveNext 方法迭代节点集合,使用 Current 属性返回位于当前节点上的 XPathNavigator 对象。 最后,使用 Value 属性检索并显示每个重复字段的值。

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 &amp; System.Environment.NewLine
Loop
MessageBox.Show(message)

前面的示例使用指定的重复域中的字符串值。 但是,如果该域包含数值,则可使用类似代码循环访问该域中的值以进行算术运算,如计算值的总计或平均数。

同样,不必使用 Value 属性来检索重复域的每个实例的值,您可以改为使用 SetValue 方法来循环访问各个域并设置它们的值,如以下示例所示。

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

使用 XPathNavigator 类访问外部数据源

若要访问与表单关联的外部数据源,请将数据源的名称传递给 XmlForm 类的 DataSources 属性。 若要创建与新外部数据源的连接,或查看现有外部数据源连接的名称列表,请单击功能区的“数据”选项卡上的“数据连接”

下面的代码示例演示如何使用 CreateNavigator 方法创建一个位于名为"CityList"的外部数据源的根节点处的 XPathNavigator 对象,然后使用 XPathNavigator 类的 OuterXml 属性在一个消息框中显示返回的 XML。 该代码示例假定您创建了一个与存储在外部数据源(如 XML 文档或 SharePoint 列表)中的城市名称列表的连接,并将该数据连接命名为"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: " &amp; _
   myNavigator.OuterXml.ToString())

在您具有对位于外部数据源的根节点处的 XPathNavigator 对象的访问权限后,您可以使用 XPathNavigator 类的成员(如 SelectSingleNodeSetValue 方法)处理该对象包含的数据。

使用 XPathNavigator 和 XPathNodeIterator 类的 InfoPath 对象模型成员

下表汇总了 Microsoft.Office.InfoPath 命名空间中所有使用 XPathNavigator 类访问、操作或提交 XML 数据的成员。

父类 成员
AdoQueryConnection
BuildSqlFromXmlNodes 方法
AdoSubmitConnection
BuildSqlFromXmlNodes 方法
ClickedEventArgs
Source 属性
ContextChangedEventArgs
Context 属性
DataSource
CreateNavigator 方法
GetNamedNodeProperty 方法
SetNamedNodeProperty 方法
EmailSubmitConnection
Execute 方法
FileQueryConnection
Execute 方法
FileSubmitConnection
Execute 方法
FormError
Site 属性
FormErrorCollection
Add 方法
FormTemplate
Manifest 属性
MergeEventArgs
Xml 属性
SharepointListQueryConnection
Execute 方法
Signature
SignatureBlockXmlNode 属性
SignedDataBlock
SignatureContainer 属性
View
GetContextNodes 方法
SelectNodes 方法
SelectText 方法
WebServiceConnection
Execute 方法
GenerateDataSetDiffGram 方法
XmlEventArgs
OldParent 属性
Site 属性
XmlForm
MainDataSource 属性,该属性返回一个 DataSource 对象,接着该对象提供 CreateNavigator 方法,用于创建位于表单的基础 XML 文档(主数据源)的根节点处的 XPathNavigator 对象。
MergeForm 方法
XmlFormCollection
NewFromFormTemplate 方法
XmlValidatingEventArgs
ReportError 方法

除了返回或接受 XPathNavigator 对象的 InfoPath 对象模型成员外,以下方法返回 System.Xml.XPath 命名空间的 XPathNodeIterator 类的实例,用来迭代在视图中指定或选择的项的 XML 节点。

父类 成员
View
GetContextNodes 方法
GetSelectedNodes 方法

使用 XPathNavigator 和 XPathNodeIterator 类处理在视图中选择的数据

下面的示例使用 XPathNavigatorXPathNodeIterator 类的成员按照以下顺序处理表单数据:

  1. 使用 DataSource 类的 CreateNavigator 方法创建一个名为 repeatingTableRow1 的 XPathNavigator 对象变量,默认情况下该对象变量位于表单的基础 XML 文档(主数据源)的根节点处。

  2. 使用 XPathNavigator 类的 SelectSingleNode 方法将 XPathNavigator 对象的位置移到“重复表”控件的第一行,该控件绑定到数据源中的 group2。

  3. 将 repeatingTableRow1 对象变量传递到 View 类的 SelectNodes 方法,以选择该行中的节点。

  4. 声明一个名为 selectedNodes 的 XPathNodeIterator 对象变量,并使用 View 类的 GetSelectedNodes 方法用所选的节点填充 XPathNodeIterator 对象。

  5. 使用 XPathNodeIterator 类的 Count 属性显示包含在 selectedNodes 对象变量中的节点数。

  6. 使用 For/Each 循环迭代 selectedNodes 对象变量中的节点,并使用 XPathNavigator 类的 NameInnerXmlValue 属性显示有关每个节点的信息。

// 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

有关如何处理 InfoPath 表单模板中的 XML 数据的详细信息,请参阅使用 InfoPath 2007 表单模板中的 XPathNavigator 类处理 XML 数据。