C# 如何合并xml流
我有多个采用这种格式的xml流: xml1:C# 如何合并xml流,c#,xml,C#,Xml,我有多个采用这种格式的xml流: xml1: 测试1 测试2 测试4 1 测试1 测试7 测试8 2 ... xmlN: 测试1 测试2 测试4 5 测试1 测试7 测试8 6 测试9 测试8 测试8 6 我希望合并的xml如下所示: <?xml version="1.0" encoding="utf-8"?> <Node> <NodeA>test1</NodeA> <NodeB>test2</No
测试1
测试2
测试4
1
测试1
测试7
测试8
2
...
xmlN:
测试1
测试2
测试4
5
测试1
测试7
测试8
6
测试9
测试8
测试8
6
我希望合并的xml如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Node>
<NodeA>test1</NodeA>
<NodeB>test2</NodeB>
<NodeNEW>test4</Att>
<Value1>1.0</Value1>
<ValueN>5.0</ValueN>
</Node>
<Node>
<NodeA>test1</NodeA>
<NodeB>test7</NodeB>
<NodeNEW>test8</NodeNEW>
<Value1>2.0</Value1>
<ValueN>6.0</ValueN>
</Node>
<Node>
<NodeA>test9</NodeA>
<NodeB>test8</NodeB>
<NodeNEW>test8</NodeNew>
<Value1></Value1>
<ValueN>6.0</ValueN>
</Node>
测试1
测试2
测试4
1
5
测试1
测试7
测试8
2
6
测试9
测试8
测试8
6
所以我创建了具有不同值1的唯一键NodeA>NodeB>NodeNEW。。。如果此唯一键未出现在其各自的xml中,则不分配任何值
做这件事最有效的方法是什么?下面的代码应该会给你想要的结果。如果没有发布,它不会显示以前节点的值,但是你可以到处玩,也可以让它工作。这里的想法是使用XMLReader读取项目,并在同一迭代中更新现有节点
static void Main(string[] args) {
//Ideally you should have well formed xml with root element as eg given below
//but since it is stream it is possible but not sure how much control you have on it.
//eg: <Nodes><Node1/><Node2/>...</Nodes>
//Reading your data from locally stored stream files
var streamFiles=new[] { @"C:\temp\stack\xml1.xml", @"C:\temp\stack\xmlN.xml" };
var dict = new Dictionary<int,XElement>();
foreach(var streamFile in streamFiles) {
using(var reader=XmlReader.Create(streamFile, new XmlReaderSettings { ConformanceLevel=ConformanceLevel.Fragment })) {
var nodeNo=0;
while(reader.MoveToContent()==XmlNodeType.Element) {
var element=XNode.ReadFrom(reader) as XElement;
//Now merge the data. Yahoo
XElement currentElement;
if(!dict.TryGetValue(nodeNo, out currentElement)) {
currentElement = new XElement("Node");
dict.Add(nodeNo, currentElement);
}
foreach(var el in element.Elements().Where(e => !e.HasElements)) {
currentElement.SetElementValue(el.Name, el.Value);
}
currentElement.SetElementValue("NodeNEW",
element.Elements().Where(e => e.HasElements)
.SelectMany(e => e.Elements()
.Where(w => w.Name=="Att"))
.FirstOrDefault().Value);
currentElement.Add(element.Elements().Where(e => e.HasElements)
.SelectMany(e => e.Elements()
.Where(w => w.Name!="Att")));
nodeNo++;
}
}
}
using(var writer=XmlWriter.Create(@"C:\temp\stack\xmlMerged.xml",
new XmlWriterSettings {
ConformanceLevel=ConformanceLevel.Fragment,
Indent=true
})) {
foreach(var element in dict.Values) {
element.WriteTo(writer);
}
}
}
static void Main(字符串[]args){
//理想情况下,您应该具有格式良好的xml,根元素如下所示
//但由于它是流,所以它是可能的,但不确定您对它有多大的控制。
//例:。。。
//从本地存储的流文件中读取数据
var streamFiles=new[]{@“C:\temp\stack\xml1.xml”、@“C:\temp\stack\xmlN.xml”};
var dict=新字典();
foreach(streamFiles中的var streamFile){
使用(var reader=XmlReader.Create(streamFile,新的XmlReaderSettings{ConformanceLevel=ConformanceLevel.Fragment})){
var nodeNo=0;
while(reader.MoveToContent()==XmlNodeType.Element){
var element=XNode.ReadFrom(reader)作为XElement;
//现在合并数据
XElement电流元件;
if(!dict.TryGetValue(nodeNo,out currentElement)){
currentElement=新的XElement(“节点”);
dict.Add(nodeNo,currentElement);
}
foreach(element.Elements()中的var el,其中(e=>!e.HasElements)){
currentElement.SetElementValue(el.Name,el.Value);
}
currentElement.SetElementValue(“NodeNEW”,
element.Elements()。其中(e=>e.HasElements)
.SelectMany(e=>e.Elements()
。其中(w=>w.Name==“Att”))
.FirstOrDefault().Value);
currentElement.Add(element.Elements()。其中(e=>e.HasElements)
.SelectMany(e=>e.Elements()
其中(w=>w.Name!=“Att”);
nodeNo++;
}
}
}
使用(var writer=XmlWriter.Create)(@“C:\temp\stack\xmlMerged.xml”,
新的XmlWriterSettings{
ConformanceLevel=ConformanceLevel.Fragment,
缩进=真
})) {
foreach(dict.Values中的var元素){
元素。WriteTo(writer);
}
}
}
反序列化、合并、序列化。您是否尝试创建相应的模型,然后使用xml属性标记属性,如xmlElement
,然后加载模型。然后以编程方式将它们合并到第三个模型中,然后使用xml序列化程序序列化为新的xml。请参阅此处的代码,为变量提供有用的名称。谢谢你指出这一点。我养成了使用下划线的习惯,但是在你的评论之后,它的用法现在很清楚了。还更新了代码。您所说的“如果未发布,则不会显示以前节点的值”是什么意思?看看您的实现,它是如何在Value1之后添加ValueN作为额外条目的?我不知道它是如何检查现有的'NodeA>NodeB>NodeNEW'组合是否已经存在的。你似乎只把一个数字当作字典里的关键字。在上一个合并节点的示例中,将不会生成空Value1标记。为了解决这个问题,所有之前的序列号都要迭代。
<?xml version="1.0" encoding="utf-8"?>
<Node>
<NodeA>test1</NodeA>
<NodeB>test2</NodeB>
<NodeNEW>test4</Att>
<Value1>1.0</Value1>
<ValueN>5.0</ValueN>
</Node>
<Node>
<NodeA>test1</NodeA>
<NodeB>test7</NodeB>
<NodeNEW>test8</NodeNEW>
<Value1>2.0</Value1>
<ValueN>6.0</ValueN>
</Node>
<Node>
<NodeA>test9</NodeA>
<NodeB>test8</NodeB>
<NodeNEW>test8</NodeNew>
<Value1></Value1>
<ValueN>6.0</ValueN>
</Node>
static void Main(string[] args) {
//Ideally you should have well formed xml with root element as eg given below
//but since it is stream it is possible but not sure how much control you have on it.
//eg: <Nodes><Node1/><Node2/>...</Nodes>
//Reading your data from locally stored stream files
var streamFiles=new[] { @"C:\temp\stack\xml1.xml", @"C:\temp\stack\xmlN.xml" };
var dict = new Dictionary<int,XElement>();
foreach(var streamFile in streamFiles) {
using(var reader=XmlReader.Create(streamFile, new XmlReaderSettings { ConformanceLevel=ConformanceLevel.Fragment })) {
var nodeNo=0;
while(reader.MoveToContent()==XmlNodeType.Element) {
var element=XNode.ReadFrom(reader) as XElement;
//Now merge the data. Yahoo
XElement currentElement;
if(!dict.TryGetValue(nodeNo, out currentElement)) {
currentElement = new XElement("Node");
dict.Add(nodeNo, currentElement);
}
foreach(var el in element.Elements().Where(e => !e.HasElements)) {
currentElement.SetElementValue(el.Name, el.Value);
}
currentElement.SetElementValue("NodeNEW",
element.Elements().Where(e => e.HasElements)
.SelectMany(e => e.Elements()
.Where(w => w.Name=="Att"))
.FirstOrDefault().Value);
currentElement.Add(element.Elements().Where(e => e.HasElements)
.SelectMany(e => e.Elements()
.Where(w => w.Name!="Att")));
nodeNo++;
}
}
}
using(var writer=XmlWriter.Create(@"C:\temp\stack\xmlMerged.xml",
new XmlWriterSettings {
ConformanceLevel=ConformanceLevel.Fragment,
Indent=true
})) {
foreach(var element in dict.Values) {
element.WriteTo(writer);
}
}
}