C# 如何合并xml流

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

我有多个采用这种格式的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</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);
    }
  }
}