Reputation: 71
Let's say I have 8 XML documents setup in the following manner.
123.xml
<link xlink="ABC">ABC</link>
<link xlink="DEF">DEF</link>
<link xlink="GHI">GHI</link>
ABC.xml
<link xlink="JKL">JKL</link>
JKL.xml
<link xlink="MNO">MNO</link>
DEF.xml
<link xlink="PQR">PQR</link>
GHI.xml
<link xlink="STU">STU</link>
MNO.xml, PQR.xml and STU.xml have no links.
I am moving through these files recursively using VB.NET starting with 123.xml and looking for xlink in each link tag. For each xlink I then look for links in that document and so on until I run out and come back to the original document for the next xlink.
The order for the example above would be 123 -> ABC -> JKL -> MNO -> DEF -> PQR -> GHI -> STU. There are multiple different ways these file structures could turn out, this is simply an example.
So if my code is similar to below and I am assigning an ID to each, just an integer that increments every time Add_Task is called, how would I go about finding out what the ID of the parent XML file is, the file that called the xlink originally? Also any links in the first XML document (123.xml) should be give a parent ID of 0, since it is in the original document and doesn't have a parent.
Public Sub Get_Next_Link(filename as String)
Dim xDoc As New XmlDocument()
xDoc.Load(filename)
Dim xNodeList As XmlNodeList = xDoc.SelectNodes("//link")
For Each xNode as XMLNode in xNodeList
Add_Task(ID, Name, ParentID)
Get_Next_Link(get the xlink attribute and + ".xml" here)
Next
End Sub
The Add_Task results of the above example should be as follows.
1, ABC, 0
2, JKL, 1
3, MNO, 2
4, DEF, 0
5, PQR, 4
6, GHI, 0
7, STU, 6
I'm having difficulties determining how to set/locate the parent ID of the link being processed. If it helps, I am putting the results of the Add_Task method into a datatable. I've tried calling the datatable with the previous link name (ABC, etc...) to get the ID but I am having issues where it is not giving me the correct parent ID so I am hoping that someone has a better method for accomplishing this.
Upvotes: 0
Views: 150
Reputation: 12748
Just pass the ID of the parent as parameter. In the example below, -1 would mean no parent.
Get_Next_Link("123.xml", -1)
Public Sub Get_Next_Link(filename as String, byval parentId as integer)
...
Get_Next_Link(get the xlink attribute and + ".xml" here, ID)
Here's a move detailed example.
Module Module1
Private DataInfo As New Dictionary(Of String, List(Of String))
Sub Main()
DataInfo.Add("123", New List(Of String) From {"ABC", "DEF", "GHI"})
DataInfo.Add("ABC", New List(Of String) From {"JKL"})
DataInfo.Add("JKL", New List(Of String) From {"MNO"})
DataInfo.Add("DEF", New List(Of String) From {"PQR"})
DataInfo.Add("GHI", New List(Of String) From {"STU"})
Get_Next_Link("123", -1)
Console.ReadLine()
End Sub
Private Sub Get_Next_Link(ByVal filename As String, ByVal parentID As Integer)
Static nextAvailableId As Integer = 0
Dim currentId As Integer = nextAvailableId
nextAvailableId += 1
Console.WriteLine(currentId & ", " & filename & ", " & parentID)
If DataInfo.ContainsKey(filename) Then
For Each link As String In DataInfo(filename)
Get_Next_Link(link, currentId)
Next
End If
End Sub
End Module
Upvotes: 1
Reputation: 34421
Using Linq :
Imports System.Data
Module Module1
Sub Main()
Dim dt As New DataTable()
dt.Columns.Add("ID", GetType(Integer))
dt.Columns.Add("Name", GetType(String))
dt.Columns.Add("Parent_ID", GetType(Integer))
dt.Rows.Add(New Object() {1, "ABC", 0})
dt.Rows.Add(New Object() {2, "JKL", 1})
dt.Rows.Add(New Object() {3, "MNO", 2})
dt.Rows.Add(New Object() {4, "DEF", 0})
dt.Rows.Add(New Object() {5, "PQR", 4})
dt.Rows.Add(New Object() {6, "GHI", 0})
dt.Rows.Add(New Object() {7, "STU", 6})
Dim parent As String = GetParent("MNO", dt)
End Sub
Function GetParent(name As String, dt As DataTable) As String
Dim parentID = dt.AsEnumerable().Where(Function(x) x.Field(Of String)("Name") = name).Select(Function(x) x.Field(Of Integer)("Parent_ID")).FirstOrDefault()
Return dt.AsEnumerable().Where(Function(x) x.Field(Of Integer)("ID") = parentID).Select(Function(x) x.Field(Of String)("Name")).FirstOrDefault()
End Function
End Module
Upvotes: 0
Reputation: 9193
Your recursive method can leverage a parameter to help with this:
Public Sub Get_Next_Link(filename As String, level As Integer)
Then in the method increment as necessary:
level += 1
For Each xNode as XMLNode in xNodeList
Add_Task(ID, Name, ParentID)
Get_Next_Link("theNextFile.xml", level)
Next
The first time you call Get_Next_Link you should pass a value of -1 for this parameter for it to behave as you desire.
In terms of "setting the parentID", a DataTable can work, but maybe a simple custom class will suffice:
Public Class CustomXmlFile
Public Property FileName As String
Public Property ID As Integer
Public Property ParentID As Integer
'Etc
End Class
Then in your class where Get_Next_Link lives:
Private m_lstCustomXMLFiles As New List(Of CustomXmlFile)
Finally at the spot where you want to set the values (perhaps in Add_Task):
Dim objFile As New CustomXmlFile()
objFile.FileName = "Set your values"
m_lstCustomXMLFiles.Add(objFile)
Upvotes: 1