[英]Returning distinct paths in XML
我有一個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
嘗試這個:
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
它正確地擺脫了重復的路徑。
感謝所有回復的人。 在研究了各種方法之后,我最終使用字典來獲得所有獨特的路徑。 對於任何可能遇到類似情況的人來說,這是我使用的:
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()
這比我想象的要糟糕得多。 我不是一個優秀的程序員,但我通常可以弄清楚如何完成它,但我的代碼通常用於小型實用程序的非常有限的使用,所以它只需要工作。
注意:現在已更新為僅輸出唯一路徑
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.