在下面的代码示例中,我想在同一个aNode
循环中遍历eNode
和For
。 For Each
语句中是否可以包含两个元素?以下是不正确的语法,但我在论坛上寻求帮助:
For Each aNode As XmlNode In aDoc.SelectNodes("//*")
And eNode As XmlNode In eDoc.SelectNodes("//*")
我需要比较两个XmlDocuments
以确保它们是相同的。我想为此任务使用单个For Each
循环。 aNode
是实际的xml结果,eNode
是预期的xml结果。 aNode
和{}}中的节点/值配对都需要相同。 eNode
。节点/值配对在运行时都是未知的,因此我无法对节点发出任何请求,然后查找该值。
答案 0 :(得分:2)
您应该能够使用LINQ's Concat来组合两个集合,然后您可以迭代这些集合:
For Each node As XmlNode In _
aDoc.SelectNodes("//*").Cast(Of XmlNode)().Concat( _
eDoc.SelectNodes("//*").Cast(Of XmlNode)())
或者,为了使其可读:
Dim l_aNodes = aDoc.SelectNodes("//*").Cast(Of XmlNode)()
Dim l_eNodes = eDoc.SelectNodes("//*").Cast(Of XmlNode)()
Dim l_allNodes = l_aNodes.Concat( l_eNodes )
For Each l_node in l_allNodes
这将获取第一个集合中的所有元素,然后将第二个集合中的所有元素附加到它的末尾(如队列)。
或者,如果您想要“zip”,可以使用Enumerable.Zip:
If Not l_aNodes.Count = l_eNodes.Count Then
...
End If
Dim l_allNodes =
Enumerable.Zip(
l_aNodes,
l_eNodes,
Function(a, e) New With { .aNode = a, .eNode = e } )
For Each l_aeNode in l_allNodes
If Not l_aeNode.aNode.Name = l_aeNode.eNode.Name Then
...
根据Enumerable.Zip的文档,
如果序列没有相同数量的元素,则该方法会合并序列,直到它们到达其中一个序列的末尾。例如,如果一个序列有三个元素而另一个序列有四个,则结果序列只有三个元素。
因此,您需要在开始之前比较集合大小。这实际上是一个好主意,因为它将节省比较每个节点所需的处理能力。
如果集合大小相同,则上面的代码从每个集合中的第一个元素开始,然后将它们组合成Anonymous Type。然后是每个集合中的第二个元素,然后是第三个元素,等等。结果是匿名类型实例的集合。
然后,您可以迭代匿名类型实例,并使用适当的属性(aNode
和eNode
)获取每个元素。
但是有一些内置语法来处理这个问题吗?不,没有。
答案 1 :(得分:0)
您可以尝试将节点作为文本存储到已排序的列表中,然后比较列表:
Dim aNodes = New List(Of String)( _
aDoc _
.SelectNodes("//*") _
.[Select](Function(n) n.ToString()) _
.OrderBy(Function(s) s))
Dim eNodes = New List(Of String)( _
eDoc _
.SelectNodes("//*") _
.[Select](Function(n) n.ToString()) _
.OrderBy(Function(s) s))
If aNodes.Count <> eNodes.Count Then
Return False
End If
For i As Integer = 0 To aNodes.Count - 1
If aNodes(i) <> bNodes(i) Then
Return False
End If
Next
Return True