How to merge xml streams

时间:2015-06-25 18:51:43

标签: c# xml

I have multiple xml streams with this format: xml1: <?xml version="1.0" encoding="utf-8"?> <Node> <NodeA>test1</NodeA> <NodeB>test2</NodeB> <NodeC> <Att>test4</Att> <Value1>1.0</Value1> </NodeC> </Node> <Node> <NodeA>test1</NodeA> <NodeB>test7</NodeB> <NodeC> <Att>test8</Att> <Value1>2.0</Value1> </NodeC> </Node> ... xmlN: <?xml version="1.0" encoding="utf-8"?> <Node> <NodeA>test1</NodeA> <NodeB>test2</NodeB> <NodeC> <Att>test4</Att> <ValueN>5.0</ValueN> </NodeC> </Node> <Node> <NodeA>test1</NodeA> <NodeB>test7</NodeB> <NodeC> <Att>test8</Att> <ValueN>6.0</ValueN> </NodeC> </Node> <Node> <NodeA>test9</NodeA> <NodeB>test8</NodeB> <NodeC> <Att>test8</Att> <ValueN>6.0</ValueN> </NodeC> </Node> I want the merged xml to look like this: <?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> So I create unique keys NodeA>NodeB>NodeNEW with different Value1, ... ValueN which are assigned nothing if this unique key does not appear in its respective xml. What would be the most efficient way to do this?

1 个答案:

答案 0 :(得分:1)

下面的代码应该为您提供所需的结果,如果它没有发布,它将不会显示以前节点的值,但是您可以使用它并使其工作。这里的想法是使用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);
    }
  }
}