我有一个显示树结构的文本文件。空格数表示给定成员的级别。例如,如下所示,组可以拥有可以拥有成员的成员或子组:
MainGroup
Member1
Member2
Group1
Member11
Member12
Group12
Member21
Member22
Member3
对不起大家, 我在这里的第一次和第一个问题是弄清楚整个格式化的事情。
这是我到目前为止所尝试的:
遍历每一行(有一列),我创建一个节点。我找到了空格的数量。如果它为零,我将属性添加到此节点并将其添加到doc。如果它有空格,我循环并继续向这个节点添加子节点。那是事情不适合我的地方。
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
答案 0 :(得分:1)
好吧,你应该读取文件(如果它不是太大就读入整个内存而不是内存),创建一个空的XML文档,遍历这些行,并根据行的缩进创建新的节点并添加它们到适当的XML元素(例如,跟踪每个级别的'last'节点并将它们添加为子元素)。当然,您可以将XML创建延迟到以后阶段,并根据文件内容构建对象层次结构,并在完成后简单地序列化。或者也许整个事情可以通过智能正则表达式来完成。有很多可能的解决方案。
但坦率地说:所以你不会毫不费力地神奇地获取代码。 (好吧,有时它是,但仍然是:告诉我们你在提出一个非常普遍的问题之前已经做了一些努力来实际解决问题。)
答案 1 :(得分:0)
这是一个相对简洁的方法:
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>