2014-04-17 71 views
0

我有一個顯示樹結構的文本文件。空格數表示給定成員的級別。例如下面,用戶組的成員或亞組誰可以擁有成員等兒子:從.NET中的文本文件構建XML樹

MainGroup 
Member1 
Member2 
Group1 
    Member11 
    Member12 
    Group12 
    Member21 
    Member22 
Member3 

對不起大家,我 第一次和第一個問題在這裏所以是搞清楚整個事情的格式。

這是我到目前爲止已經試過:(這是沒有必要的,但我需要的數據表,以顯示我的數據)

  1. 我讀的文本文件導入數據表。
  2. 通過每行(有一列),我創建一個節點。我找到了空格的數量。如果它爲零,我將屬性添加到此節點並將其添加到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 
    
+1

您嘗試了什麼?你在哪裏遇到問題?發佈您的代碼。 – qqbenq

+0

你能解釋一下「空格數表示給定成員的級別」是什麼意思嗎?它是一個固定寬度的文本文件嗎? – wooters

回答

1

那麼,你應該閱讀該文件(如果它不是太大讀取整個入內存,否則不會),創建一個空的XML文檔,通過線迭代,並且根據的壓痕行創建新節點並將它們添加到適當的XML元素(例如跟蹤每個級別的「最後」節點並將它們添加爲子元素)。當然,您可以將XML創建延遲到以後的階段,並根據文件內容構建對象層次結構,並在完成後簡單地序列化它。或者,也許這整個事情可以用一個聰明的正則表達式來完成。有很多可能的解決方案。

但坦率地說:SO不是你不費力就能神奇地獲得代碼的地方。 (當然,有時,但儘管如此:告訴我們你做一些努力,你問一個非常普遍的問題之前,其實解決這個問題。)

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> 
+0

這正是我想要做的。謝謝! – user3546141