Генерация XML-файлов с помощью рекурсии (самосоединяющейся таблицы), не дающая желаемой иерархии

#xml #vb.net #recursion #xmltextwriter

#xml #vb.net #рекурсия #xmltextwriter

Вопрос:

У меня есть задача генерации XML-файлов из данных, заполненных в самосоединяющейся таблице; все XML-файлы должны соответствовать иерархии, как определено в самосоединении.

Я написал некоторый рекурсивный код для достижения этого с некоторым успехом, но моя логика, похоже, никогда не отображает иерархии правильно; некоторый родительский узел всегда блокирует отображение как родительских узлов, так и дочерних узлов — без потомков.

Например, у меня есть следующая идеальная структура XML:

  <?xml version="1.0" encoding="utf-8"?>  
 <MYREPORT>  
   <HEADER>  
    <HEADER_ID></HEADER_ID>  
    <HEADER_DESC></HEADER_DESC>  
    <HEADER_CODE></HEADER_CODE>  
    <HEADER_NAME></HEADER_NAME>  
    <HEADER_DATE></HEADER_DATE>  
    <HEADER_DATE2></HEADER_DATE2>  
    <AS_AT></AS_AT>  
  </HEADER>  
  <BODY>   
    <ITEMS_INFO>  
      <ITEM_CODE></ITEM_CODE>  
      <ITEM_DESC></ITEM_DESC>  
      <AMOUNT></AMOUNT>  
    </ITEMS_INFO>  
  </BODY>  
</MYREPORT>  
  

При этом данные подаются из следующей самосоединяющейся таблицы (первичный ключ: ElementId , внешний ключ: ParentId )

 ElementId   ElementName         ParentId    ElementLevel 
1           MYREPORT            NULL            0  
2       HEADER              1           1  
3       HEADER_ID           2           2  
4       HEADER_DESC         2           2  
5       HEADER_CODE         2           2  
6       HEADER_NAME         2           2  
7       HEADER_DATE         2           2  
8       HEADER _DATE2           2           2  
9       AS_AT               2           2  
10      BODY                1           1  
12      ITEMS_INFO          10          2  
13      ITEM_CODE           12          3  
14      ITEM_DESC           12          3  
15      AMOUNT              12          3  
  

Но я продолжаю получать следующий XML-вывод, где <ITEMS_INFO></ITEMS_INFO> отображается как parentNode блок (что правильно), а также childNode — без потомков (что неправильно)

 <?xml version="1.0" encoding="utf-8"?>
<MYREPORT>
  <HEADER>
    <HEADER_ID>8:564</HEADER_ID>
    <HEADER_DESC>9:564</HEADER_DESC>
    <HEADER_CODE>10:564</HEADER_CODE>
    <HEADER_NAME>11:564</HEADER_NAME>
    <HEADER_DATE>12:564</HEADER_DATE>
    <HEADER_DATE2>13:564</HEADER_DATE2>
    <AS_AT>14:564</AS_AT>
 </HEADER>
 <BODY>
    <ITEMS_INFO>
      <ITEM_CODE>17:737</ITEM_CODE>
      <ITEM_DESC>18:737</ITEM_DESC>
      <AMOUNT>19:737</AMOUNT>
    </ITEMS_INFO>
    <ITEMS_INFO>20:737</ITEMS_INFO>
  </BODY>
</MYREPORT>
  

Пожалуйста, просмотрите мой код рекурсии на предмет любых логических лазеек и того, как я могу наилучшим образом достичь своей идеальной иерархии XML

 Private xmlWriter As New XmlTextWriter(My.Settings.xmlPath amp; "Rep.xml", System.Text.Encoding.UTF8)
Sub Main()

    Try
        Dim ds As DataSet = SqlHelper.ExecuteDataset(My.Settings.SqlUserRoleServices, CommandType.StoredProcedure, "getTest")
        ds.Tables(1).Columns.Add("isParsed", GetType(System.Int16))
        ds.Tables(1).AcceptChanges()
        Dim dr As DataRelation = New DataRelation("ElementSelf", ds.Tables(1).Columns("ElementId"), ds.Tables(1).Columns("ParentId"), True)
        ds.Relations.Add(dr)

        xmlWriter.Formatting = Formatting.Indented
        For Each StartRow As DataRow In ds.Tables(0).Rows
            If StartRow.IsNull("ParentId") Then
                xmlWriter.WriteStartDocument()
                xmlWriter.WriteStartElement(StartRow("ElementName"))
            End If
        Next

        For Each parentRow As DataRow In ds.Tables(1).Rows
            If (Not parentRow.IsNull("ParentId")) And parentRow.IsNull("IsParsed") Then
                parentRow("IsParsed") = 1
                doRecursion(parentRow, dr, xmlWriter)
                parentRow.AcceptChanges()
            End If
        Next

        xmlWriter.WriteEndElement()
        xmlWriter.WriteEndDocument()
        xmlWriter.Flush()
        xmlWriter.Close()
    Catch ex As Exception
        Console.WriteLine(ex.Message)
        Console.ReadKey()
    End Try
End Sub

Private Sub doRecursion(ByRef parentRow As DataRow, ByRef dr As DataRelation, ByRef xmlwriter As XmlTextWriter)
    Dim children As DataRow() = parentRow.GetChildRows(dr)

    If children.Any Then
        xmlwriter.WriteStartElement(parentRow("ElementName").ToString)

        For Each brow As DataRow In children
            If brow("IsParsed") Is DBNull.Value Then
                brow("IsParsed") = 1
                brow.AcceptChanges()
                doRecursion(brow, dr, xmlwriter)
                xmlwriter.WriteElementString(brow("ElementName"), Date.Now.Second amp; ":" amp; Date.Now.Millisecond)
                System.Threading.Thread.Sleep(1000)
                brow.AcceptChanges()
                parentRow.AcceptChanges()
            Else
                Exit For
            End If
        Next
        xmlwriter.WriteEndElement()
    Else
        Return
    End If
End Sub
  

Спасибо.