我有一个包含以下行的文本文件:
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>
现在我想将这些节点合并到我首先描述的格式中。
感谢您的帮助。 :)
答案 0 :(得分: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
答案 1 :(得分:0)
您好请查看此链接,该链接对您的搜索内容非常有用
答案 2 :(得分: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>