Search code examples
c#xmllinqxml-parsingxmlhttprequest

Merge two xml files from two memory streams using linq and print the new file


--edit I will worry about memory stream later, how do I combined the strings first and print the output? --edit

string1 xml

<study-groups>
  <study-group>
    <name></name>
    <uuid></uuid>
    <href></href>
  </study-group>
</study-groups>

xml string2

<studies>
 <study>
    <name>someValue</name>
    <uuid>someValue</uuid>
    <href>someValue</href>
    <parent-uuid>someValue</parent-uuid>
    <created-at>2015-08-12T17:51:03Z</created-at>
    <updated-at>2016-06-18T05:53:01Z</updated-at>
  </study>
  <study>
    <name></name>
    <uuid></uuid>
    <href></href>
    <parent-uuid></parent-uuid>
    <created-at>2015-08-12T17:51:03Z</created-at>
    <updated-at>2016-06-18T05:53:01Z</updated-at>
  </study>
</studies>

I am looping through API HTTP requests and saving the output xml to a string and to a memory stream. the first foreach loop produces a single xml file. in my second for each loop, it returns multiple files. I want to join string1 and string2 to create string 3 without duplicates and pass string 3 into the third 4 each loop.

var xml1 = XDocument.Parse(string1);
var xml2 = XDocument.Parse(string2);


//Combine and remove duplicates
var string3 = xml1.Descendants("study-groups")
    .Union(xml2.Descendants("studies"));

Console.WriteLine("---------------------string 3---------------------------");
Console.WriteLine(string3.ToString());
Console.WriteLine("---------------------string 3---------------------------");

//Combine and keep duplicates
var combinedWithDups = xml1.Descendants("study-groups")
    .Concat(xml2.Descendants("studies"));

foreach (var i in combinedUnique)
{
    Console.WriteLine("---------------------combinednodups---------------------------");
    Console.WriteLine("{0}", i);
    Console.WriteLine("---------------------combinednodups---------------------------");
}

but my output keeps coming out as:

System.Linq.Enumerable+UnionIterator2`1[System.Xml.Linq.XElement]


Solution

  • If the problem is simply the output, it's because calling ToString() on an IEnumerable (like most types) will simply print the name of the type.

    Instead you could do:

    // Join each element in the IEnumerable with a line break
    Console.WriteLine(string.Join(Environment.NewLine, string3));
    

    This will produce the following with your example input:

    <study-groups>
      <study-group>
        <name></name>
        <uuid></uuid>
        <href></href>
      </study-group>
    </study-groups>
    <studies>
      <study>
        <name>someValue</name>
        <uuid>someValue</uuid>
        <href>someValue</href>
        <parent-uuid>someValue</parent-uuid>
        <created-at>2015-08-12T17:51:03Z</created-at>
        <updated-at>2016-06-18T05:53:01Z</updated-at>
      </study>
      <study>
        <name></name>
        <uuid></uuid>
        <href></href>
        <parent-uuid></parent-uuid>
        <created-at>2015-08-12T17:51:03Z</created-at>
        <updated-at>2016-06-18T05:53:01Z</updated-at>
      </study>
    </studies>
    

    However, if that's all you want, there's no need for using an XDocument. You can simply concatenate the two strings:

    var string3 = string1 + Environment.NewLine + string2;
    Console.WriteLine(string3);