我有一个XML文件,我想从中检索所有唯一路径。在以下示例中:
<?xml version="1.0" encoding="utf-8"?>
<views>
<invoice>
<newRa elem="0">
<createD>20150514</createD>
<modD>1234</modD>
<sample>text</sample>
</newRa>
<total>1.99</total>
</invoice>
</views>
我想要检索:
views/invoice/newRa/createD
views/invoice/newRa/modD
views/invoice/newRa/sample
and so on......
我对xPath有一些经验,但我不知道如何在VB中设置一个sub来为我做这个。请注意,我正在使用.NET 2.0,因此LINQ是不可能的。
编辑1:
Dim xOne As New XmlDocument
xOne.Load("d/input/oneTest.xml")
For Each rNode As XmlNode In xOne.SelectSingleNode("/")
If rNode.HasChildNodes Then
subHasChild(rNode)
End If
Next
Private Sub subHasChild(ByVal cNode As XmlNode)
Dim sNode = cNode.Name
If cNode.HasChildNodes Then
sNode = sNode + "/" + cNode.FirstChild.Name
cNode = cNode.FirstChild
subHasChild(cNode)
End If
Dim sw As New StreamWriter("d:\input\paths.txt")
sw.WriteLine(sNode)
sw.Flush() : sw.Close() : sw.Dispose()
End Sub
答案 0 :(得分:2)
试试这个:
Dim xd = <?xml version="1.0" encoding="utf-8"?>
<views>
<invoice>
<newRa elem="0">
<createD>20150514</createD>
<modD>1234</modD>
<sample>text</sample>
</newRa>
<total>1.99</total>
</invoice>
</views>
Dim getPaths As Func(Of XElement, IEnumerable(Of String)) = Nothing
getPaths = Function(xe) _
If(xe.Elements().Any(), _
xe.Elements() _
.SelectMany( _
Function(x) getPaths(x), _
Function(x, p) xe.Name.ToString() + "/" + p) _
.Distinct(), _
{ xe.Name.ToString() })
Dim paths = getPaths(xd.Root)
它给了我:
views/invoice/newRa/createD
views/invoice/newRa/modD
views/invoice/newRa/sample
views/invoice/total
它正确地摆脱了重复的路径。
答案 1 :(得分:1)
感谢所有回复的人。在研究了各种方法之后,我最终使用字典来获得所有独特的路径。对于任何可能遇到过类似情况的人来说,这就是我所使用的:
Dim xdDoc As New SmlDocument
Dim sw As New StreamWriter("Output File Path")
Dim diElements As New Dictionary(Of String, Integer)
xdDoc.Load("File Path")
For Each rootNode As XmlNode In xdDoc.SelectNodes("//*")
Dim sNode As String = rootNode.Name
While Not rootNode.ParentNode Is Nothing _
AndAlso Not rootNode.ParentNode.Name Is "invoice" _
AndAlso Not rootNode.ParentNode.Name Is "#document"
rootNode = rootNode.ParentNode
sNode = rootNode.Name + "/" + sNode
End While
If Not diElements.ContainsKey(sNode) Then
diElements.Add(sNode, 1)
Else
diElements(sNode) += 1
End If
Next
End While
Dim pair As KeyValuePair(Of String, Integer)
For Each pair In diElements
sw.WriteLine("{0} --- {1}", pair.Value, pair.Key)
Next
sw.Flush() : sw.Close() : sw.Dispose()
答案 2 :(得分:0)
这比我想象的要糟糕得多。我不是一个真正优秀的程序员,但我通常可以弄清楚如何完成它,但我的代码通常仅用于小型实用程序,因此它只需要工作。
注意:现在已更新为仅输出唯一路径
Private PathArray As New ArrayList
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim xDoc As New XmlDocument
Dim Output As String = ""
xDoc.Load("C:\inetpub\wwwroot\SqlMonitor\MonitorConfig.xml")
NodeRecurser(xDoc.SelectSingleNode("/"))
For Each item In PathArray
Output += item & vbCrLf
Next
MsgBox(Output)
Me.Close()
End Sub
Sub NodeRecurser(xNode As XmlNode)
If xNode.HasChildNodes Then
For Each cNode As XmlNode In xNode.ChildNodes
NodeRecurser(cNode)
Next
Else : GetPath(xNode)
End If
End Sub
Sub GetPath(n As XmlNode)
Dim xPath As String = ""
Do
If n.ParentNode.Name <> "#document" Then
xPath = n.ParentNode.Name & "/" & xPath
n = n.ParentNode
Else : Exit Do
End If
Loop
If xPath.Length > 1 And Not PathArray.Contains(xPath) Then PathArray.Add(xPath)
End Sub