过滤XML 数据:
让我们在假设一下,如果在一个真实的联系应用程序中,用户可能不希望在分级的treeview中看到“email”,”city ” 或者“country”,他们可能更希望看到顶级的用户联系身份内容,例如Alex, Rebekah, 或者 Justin,既然这样联系点的相应的详细信息(email,city )就处于相邻的可以编辑的区域,类似的用户也可能希望通过上下拖拉树节点来重新排列他们,然而在个体联系点内部通过treeview控件移动 email 地址或者city 是没有意义的。人们通常希望用一个分等级的视图去组织数据,而不简单的是对他们进行分类,换句话对联系(contact)进行重新排序分组是很正常的要求,除非city 和country 元素与指定联系的关联是很清晰,而且你可能希望单独的处理他们,而不是把他们进行分组分对。
一个很好的解决方案是当显示联系树时隐藏子节点,例如你可以为email. Address等不想显示的子元素添加一个特殊的属性(例如view=”hide”),这样在组装树控件时在组装方法中设置这个特殊属性,从而可以忽略任何元素(包括他们的子节点),虽然这样可以工作,但是改变数据源来适合用户显示不是一个很可靠的设计思路
一个更好的思路是在给定的文档内部为数据客户定义分级视图是否可见的结构,你可以通过修改populateTreeControl() 方法以使它支持xpath 例如:
[C#]
private void populateTreeControl(System.XML.XMLNode document,
System.Windows.Forms.TreeNodeCollection nodes)
{
foreach (System.XML.XMLNode node in
document.ChildNodes)
{
System.XML.XMLNode expr =
node.SelectSingleNode(xpath_filter);
if (expr != null)
{
TreeNode new_child = new
TreeNode(expr.Value);
nodes.Add(new_child);
populateTreeControl(node, new_child.Nodes);
}
}
}
[VB]
Private Sub populateTreeControl( _
ByVal document As System.XML.XMLNode, _
ByVal nodes As
System.Windows.Forms.TreeNodeCollection)
Dim node As System.XML.XMLNode
For Each node In document.ChildNodes
Dim expr As System.XML.XMLNode = _
node.SelectSingleNode(xpath_filter)
If Not (expr Is Nothing) Then
Dim new_child As New TreeNode(expr.Value)
nodes.Add(new_child)
populateTreeControl(node, new_child.Nodes)
End If
Next
End Sub
在类级别范围上添加下面的行:
[C#]
private string xpath_filter =
"@id[parent::contacts or parent::contact]";
[VB]
Private xpath_filter As String = _
"@id[parent::contacts or parent::contact]"
你可以使用xpath查询返回的结果来决定是否递归调用装入子节点,这个查询建立了一个包含规则,读“Select the id attribute of any 'contacts' or 'contact' element.",同样你也可以使用一个排除规则去确定你需要拒绝哪一个数据。
attribute::id[not(parent::email or
parent::city or parent::country)]
这不是一个通用的解决方案,但是像这样基于父子关系的过滤比基于没有限制的节点或者属性要好很多,当用户拥有充足的可编辑权限而不妨碍它的层次时,这是一个表达一个XML文档基本结构的很有效的方法。既然这样一个简单的查询就已经足够了 ,除非你需要进行更复杂的操作