从.NET中的文本文件构建XML树
本文关键字:构建 XML 文件 文本 NET | 更新日期: 2023-09-27 17:58:44
我有一个显示树结构的文本文件。空格数表示给定成员的级别。例如下面的例子,组可以有成员,也可以有成员的子组:
MainGroup
Member1
Member2
Group1
Member11
Member12
Group12
Member21
Member22
Member3
对不起大家,我在这里的第一次也是第一个问题是弄清楚整个格式化的事情。
这就是我迄今为止所尝试的:
- 我正在将文本文件读取到数据表中(这不是必要的,但我需要数据表来为我显示数据。)
遍历每一行(有一列),我创建一个节点。我找到了空格的数目。如果它为零,我会将属性添加到该节点并将其添加到文档中。如果它有空格,我循环遍历并不断向该节点添加子节点。这就是事情对我不起作用的地方。
Sub ExportToEXML Dim datarow As DataRow Dim fileName As String = "" Dim level As Integer = 0 Dim counter As Integer = 0 Dim doc As XmlDocument = New XmlDocument Dim docNode As XmlNode = doc.CreateXmlDeclaration("1.0", "UTF-8", Nothing) doc.AppendChild(docNode) Dim ComponentsNode As XmlNode = doc.CreateElement("Components") doc.AppendChild(ComponentsNode) Dim firstrow As DataRow For i As Integer = 0 To dt.Rows.Count - 1 firstrow = dt.Rows.Item(i) fileName = firstrow(0) level = CountSpacesBeforeFirstChar(fileName) Dim partNode As XmlNode = doc.CreateElement("Component") Dim att As XmlAttribute = doc.CreateAttribute("Name") att.Value = fileName partNode.Attributes.Append(att) GetChildNodes(partNode, i, doc, 0, level, dt) ComponentsNode.AppendChild(partNode) Next doc.Save("D:'TestXML.xml") End Sub Private Sub GetChildNodes(ByRef xNode As XmlNode, ByRef rowInd As Integer, ByRef xDoc As XmlDocument, level As Integer, table As DataTable) Dim lev As Integer Dim fileName As String Dim dr As DataRow For i As Integer = rowInd + 1 To table.Rows.Count - 1 dr = table.Rows.Item(i) fileName = dr(0) lev = CountSpacesBeforeFirstChar(fileName) If lev = 0 Then 'has no children Exit Sub End If If lev > level Then Dim partNode As XmlNode = xDoc.CreateElement("Component") Dim att As XmlAttribute = xDoc.CreateAttribute("Name") att.Value = fileName partNode.Attributes.Append(att) xNode.AppendChild(partNode) GetChildNodes(xNode, i, xDoc, lev, table) End If Next End Sub
好吧,您应该读取文件(如果文件不太大,则将整个文件读取到内存中,否则就不读取),创建一个空的XML文档,遍历行,并根据行的缩进创建新的节点,并将它们添加到适当的XML元素中(例如,跟踪每个级别的"最后一个"节点,然后将它们作为子元素添加)。当然,您可以将XML创建推迟到稍后阶段,并基于文件内容构建对象层次结构,并在完成后简单地序列化它。或者这整件事可以用一个智能正则表达式来完成。有很多可能的解决方案。
但坦率地说:SO不是一个你可以毫不费力地神奇地获得代码的地方。(好吧,有时确实如此,但尽管如此:在你问一个非常普遍的问题之前,向我们展示你为实际解决问题付出了一些的努力。)
这里有一个相对简洁的方法:
Sub ParseHierarchy(ByRef inputFilePath As String, ByRef outputFilePath As String)
' We'll treat depth as zero-based to match the number of spaces in the lines
Dim depth As Integer = -1
Dim settings As XmlWriterSettings = New XmlWriterSettings
settings.Indent = True
Using writer As XmlWriter = XmlWriter.Create("testxml.xml", settings)
For Each line As String In File.ReadLines(inputFilePath)
Dim nextDepth As Integer = GetLineDepth(line)
If nextDepth - depth > 1 Then
Throw New ApplicationException( _
"Depth cannot increase by more than 1 at a time.")
End If
'' Close any elements at a deeper or the same depth as the next one
CloseElements(writer, depth - nextDepth + 1)
depth = nextDepth
writer.WriteStartElement("Component")
writer.WriteAttributeString("Name", line.Trim())
Next
'' Close any elements that are still open
CloseElements(writer, depth + 1)
End Using
End Sub
Private Sub CloseElements(ByRef writer As XmlWriter, ByVal count As Integer)
For i = 1 To count
writer.WriteEndElement()
Next
End Sub
Private Function GetLineDepth(line As String) As Integer
Return Regex.Match(line, "^'s*").Length
End Function
当在示例文件上运行时,输出为:
<Component Name="MainGroup">
<Component Name="Member1" />
<Component Name="Member2" />
<Component Name="Group1">
<Component Name="Member11" />
<Component Name="Member12" />
<Component Name="Group12">
<Component Name="Member21" />
<Component Name="Member22" />
</Component>
</Component>
<Component Name="Member3" />
</Component>