2016-02-26 28 views
1

我有如下的文本文件:INI類型的純文本文件到XML在C#

root_node1_node2_node3=value 
root_node1_node2_node3=value 
root_node1_node2_node3_node4=value 
root_node5_node6=value 

我希望得到什麼:

<root> 
    <node1> 
    <node2> 
     <node3>value</node3> 
     <node3>value</node3> 
     <node3> 
     <node4>value</node4> 
     </node3> 
    </node2> 
    </node1> 
    <node5> 
    <node6>value</node6> 
    </node5> 
</root> 

所以我想轉換不同長度的線條到XML節點,然後將它們合併到C#中的單個XML文件中。
我閱讀了關於LINQtoXML的內容,但我還是對它有所瞭解。

請幫忙。


這就是我現在所在:

 // file 
     string fileName = Path.GetFileName(file); 
     string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); 
     string fileSourceDirectory = Path.GetDirectoryName(file); 

     // xml 
     XDocument xDoc = new XDocument(
      new XDeclaration("1.0", "utf-8", null), 
      // root 
      new XElement(fileNameWithoutExtension) 
      ); 

     try 
     { 
      using(StreamReader sr = new StreamReader(file)) 
      { 
       string line; 

       // go line-by-line 
       while((line = sr.ReadLine()) != null) 
       { 

        Console.WriteLine(line); 

        // element=value -> [element, value] 
        string[] elementAndValue = line.Split('='); 
        // elment_element_element -> [element, elelement, element] 
        string[] elements = elementAndValue[0].Split('_'); 
        // value 
        string value = elementAndValue[1]; 

        List<XElement> elementList = new List<XElement>(); 

        for(int i = 0; i < elements.Length; i++) 
        { 
         if(i == (elements.Length - 1)) 
         { 
          elementList.Add(new XElement(elements[i], value)); 
          Console.WriteLine("Added: " + elements[i] + "=" + value); 
         } 
         else 
         { 
          elementList.Add(new XElement(elements[i])); 
          Console.WriteLine("Added: " + elements[i]); 
         } 
        } 

        xDoc.Root.Add(elementList[0]); 
        Console.WriteLine("Added first item to root."); 

        for(int i = 0; i < elementList.Count - 1; i++) 
        { 
         elementList[i].Add(elementList[i + 1]); 
         Console.WriteLine("Added " + elementList[i + 1] + " to " + elementList[i]); 
        } 

       } 
      } 
     } 
     catch(Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 

     // save xml 
     xDoc.Save(outputDir + "\\" + fileNameWithoutExtension + ".xml"); 

這做的第一部分是我想要的。

輸出是現在這樣的:

<root> 
    <node1> 
    <node2> 
     <node3>value</node3> 
    </node2> 
    </node1> 
    <node1> 
    <node2> 
     <node3>value</node3> 
    </node2> 
    </node1> 
    <node1> 
    <node2> 
     <node3> 
     <node4>value</node4> 
     </node3> 
    </node2> 
    </node1> 
    <node5> 
    <node6>value</node6> 
    </node5> 
</root> 

現在我想這些節點合併,這是我介紹的第一個地方的格式。

謝謝你的幫助。 :)

回答

1

什麼試試這個非常有用,

 XDocument xDoc = new XDocument(); 

     while ((line = sr.ReadLine()) != null) 
     { 
      string[] nodes = line.Split('_');    
      for (int j = 0; j < nodes.Length; j++) 
      { 
       if(j == 0) // assume that all line should start with same root name 
       { 
        if (xDoc.Root == null) 
        { 
         var root = new XElement(nodes[j]); 
         xDoc.Add(root); 
        } 
       } 
       else 
       { 
        var previousNode = xDoc.Descendants(nodes[j - 1]).FirstOrDefault(); 
        if (nodes[j].Contains('=')) 
        { 
         var elementValues = nodes[j].Split('='); 

         if (previousNode.DescendantNodes().Count() == 1 && previousNode.Value != "") 
         { 
          previousNode.AddAfterSelf(new XElement(nodes[j - 1], new XElement(elementValues[0], elementValues[1])));          
         } 
         else 
         { 
          previousNode.Add(new XElement(elementValues[0], elementValues[1])); 
         } 
        } 
        else 
        { 
         var node = xDoc.Descendants(nodes[j]);        
         if (node.Count() == 0) 
         { 
          previousNode.Add(new XElement(nodes[j])); 
         } 
        } 
       } 
      } 

可行的解決方案:.NET Fiddle

+0

請不同的測試用例正確的測試代碼,如果需要的話請 –

0

還有一個執行:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Xml.Linq; 

namespace Ini2XML 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      string[] lines = new string[] { 
      "root_node1_node2_node3 = value", 
      "root_node1_node2_node3 = value1", 
      "root_node1_node2_node3_node4 = value", 
      "root_node5_node6 = value", 
      "root_node5_node6_node7_node8_node8 = value", 
      "root_node55 = value2 2232 2 232 2 2 " 
      }; 

      XDocument xml = Ini2XMLConverter.ConvertStringArrayToXML(lines); 
      xml.Save(Console.Out); 

     } 

     public class Ini2XMLConverter 
     { 
      public static XDocument ConvertStringArrayToXML(IEnumerable<string> lines) 
      { 
       if (lines == null) { return null; }; 

       XDocument xml = new XDocument(); 
       foreach (string s in lines) 
       { 
        //define path and value from each line 
        string[] sp = s.Split('='); 

        string[] path = sp[0].Trim().Split('_'); 
        string value = sp[1].Trim(); 

        //node to attach the current node 
        XElement attachTo = null; 

        for (int i = 0; i < path.Length; i++) 
        { 
         XElement currentNode = null; 

         if (i == path.Length - 1) 
         { //last node it's a TEXT node with value after "=" 
          currentNode = new XElement(path[i], value); 
         } 
         else 
         { //a simple node in the middle 
          currentNode = new XElement(path[i]); 
         } 

         // adding the root 
         if (xml.Root == null) 
         { 
          xml.Add(currentNode); 
          attachTo = currentNode; 
          continue; 
         } 
         else if (attachTo == null) 
         { //If it's a root then the first elements have to be the same 
          attachTo = xml.Root; 
          continue; 
         } 

         //looking for the same name node 
         XElement f = attachTo.Descendants(currentNode.Name).Count() == 0 ? null : attachTo.Descendants(currentNode.Name).First(); 

         //skip elements with TEXT values 
         if ((f != null) && (f.LastNode != null) && (f.LastNode.NodeType == System.Xml.XmlNodeType.Text)) { f = null; } 

         if (f == null) 
         { 
          //add new node 
          attachTo.Add(currentNode); 
          attachTo = currentNode; 
         } 
         else 
         { //don't add node if it exists already. Just move pointer to it. 
          attachTo = f; 
         } 

        } 
       } 
       return xml; 

      } 
     } 
    } 
} 

輸出:

<root> 
    <node1> 
    <node2> 
     <node3>value</node3> 
     <node3>value1</node3> 
     <node3> 
     <node4>value</node4> 
     </node3> 
    </node2> 
    </node1> 
    <node5> 
    <node6>value</node6> 
    <node6> 
     <node7> 
     <node8> 
      <node8>value</node8> 
     </node8> 
     </node7> 
    </node6> 
    </node5> 
    <node55>value2 2232 2 232 2 2</node55> 
</root> 
+0

謝謝您的解決方案,以及它的變化! :) – czondi