Deserialize XML containing a Dictionary - c#

I have an XML file containing identifiers that I would like Get, the xml look like
<Dictionary
x:TypeArguments="x:String, x:Object"
xmlns="clr-namespace:System.Collections.Generic;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<List x:TypeArguments="x:Int32" x:Key="key" Capacity="4">
<x:Int32>60371408</x:Int32>
<x:Int32>60371409</x:Int32>
</List>
</Dictionary>
The identifiers that I want to get is 60371408, 60371409

I just found a solution :
Thank you for your reaction :D

Create an XmlSerializer:
var serializer = new XmlSerializer(typeof(Dictionary<string, object>));
...then deserialize. You haven't specified what form this XML is in, whether you have a string or a stream, for example. Here's how you'd deserialize an XML string:
var reader = new StringReader(xml);
var dict = serializer.Deserialize(reader);
Now you have your Dictionary<string, object>, but since values are plain objects, you'll need to cast the values:
var list = (List<int>)dict["key"];

Try xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
public class Program
{
const string FILENAME = #"c:\temp\test.xml";
public static void Main()
{
XDocument doc = XDocument.Load(FILENAME);
XElement dictionary = doc.Descendants().Where(x => x.Name.LocalName == "Dictionary").FirstOrDefault();
XNamespace xNs = dictionary.GetNamespaceOfPrefix("x");
var results = dictionary.Descendants(xNs + "Int32").Select(x => (int)x).ToList();
}
}
}

Related

Get Each Value on an XML Node

I have an XML that looks like this:
<HiddenTopicsValues TopicCodes="TopicValues">
<Topic>
<Code>topic_aboutme</Code>
<Value>1</Value>
</Topic>
<Topic>
<Code>topic_aboutyou</Code>
<Value>1</Value>
</HiddenTopicsValues>
My goal is to create a Dictionary that lets the <Code> act as the Key, and <Value> as the Value (of the Dictionary). I declared the dictionary as shown below:
Dictionary<string,int> dictionary_topics = new Dictionary<string,int>();
And used a for loop to iterate all the values in the XML:
// Load XML Document
XmlDocument xmlTopics = new XmlDocument();
xmlTopics.Load(path);
// Get All Hidden Topics
XmlNodeList ndTopics = xmlTopics.GetElementsByTagName("Topic");
for (int i = 0; i < ndTopics.Count; i++)
{
string _topicCode = ndTopics[i].InnerText[0].ToString();
int _topicValue = ndTopics[i].InnerText[1].ToString();
// Add Topic to Dictionary
dictionary_topics.Add(_topicCode, _topicValue);
}
I thought that this: ndTopics[i].InnerText[0] would return this: topic_aboutme
And this: ndTopics[0].InnerText[1] would return this: 1
Based on the given XML.
I tried displaying ndTopics[0].InnerText and it shows this:
topic_aboutme1
How can I separate the topic_aboutme(<Code>) and 1(<Value>)?
Forgive my naiveness, I'm not really used in utilising XML.
Real easy in Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
Dictionary<string, string> dict = doc.Descendants("Topic")
.GroupBy(x => (string)x.Element("Code"), y => (string)y.Element("Value"))
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}

Finding Specific xml nodes using XDocument

I am trying to find specific nodes in xml using XDocument. The xml also has a namespace which am importing.
Below is the xml specs
<?xml version="1.0" encoding="UTF-8"?>
<tns:response xmlns:tns="http://amazon.com/amazonservices">
<tns:responseDirect>
<tns:responseExtract>
<tns:A>ExtractName</tns:A>
</tns:responseExtract>
<tns:responses>
<tns:Name>Response1</tns:Name>
<tns:Include>No</tns:Include>
</tns:responses>
<tns:responses>
<tns:Name>Response2</tns:Name>
<tns:Include>Yes</tns:Include>
</tns:responses>
<tns:responses>
<tns:Name>Response3</tns:Name>
</tns:responses>
</tns:responseDirect>
I want to retrieve all responses and also only those nodes which have Include nodes present.
I am trying below code to fetch it but I am getting none of the nodes.
XDocument document = XDocument.Parse(xml);
var name = from nm in document.Elements("responses")
select nm;
Can anyone let me know how to fix the issue?I need to only fetch the response node.
Thanks in Advance
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetNamespaceOfPrefix("tns");
var results = doc.Descendants(ns + "responses")
.Where(x => x.Elements(ns + "Include").Any())
.Select(x => new {
include = (string)x.Element(ns + "Include"),
name = (string)x.Element(ns + "Name")
}).ToList();
}
}
}

Add additional elements from a dictionary to the XML during serialization in C#

A part of the XML looks like this.
<element>
<subelment1>text</subelement1>
<subelement2>text2</subelement2>
...
</element>
It has a lot of sub elements.
I would like to add additional elements during the serialization, but the number and name is always different.
So it will be something like this:
<element>
<subelment1>text</subelement1>
<subelement2>text2</subelement2>
...
<additionalelement1>element1text</additionalelement1>
<additionalelement2>element2text</additionalelement2>
...
</element>
The additional elements are stored in a dictionary, where the element name is the key.
Is there a way to accomplish this with the XmlSerializer or any other serializer?
I post this solution a lot :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication34
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement element = doc.Descendants("element").FirstOrDefault();
Dictionary<string,string> dict = element.Elements().GroupBy(x => x.Name.LocalName, y => (string)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}

How to get all descendants with a particular attribute - Linq to Xml

<Grid>
<StringColumn Header="Name"/>
<DateColumn Header="Date"/>
</Grid>
There is probably an existing answer to this question, but I cannot seem to find it.
I need to find all xml elements which have an attribute of "Header"
The name of the element can be different.
How do I do that with Linq to XML?
This should give you the required elements:
XDocument document = ...;
var elementsWithHeader = document.Descendants()
.Where(e => e.Attributes().Any(a => a.Name == "Header"));
Something like this should work:
IEnumerable<XElement> elements =
from el in root.Elements("Grid")
where (string) el.Attribute("Header") != null
select el;
Use this:
var grid = XElement.Parse(#"<Grid>
<StringColumn Header=""Name""/>
<DateColumn Header=""Date""/>
</Grid>");
var elements = grid.XPathSelectElements(".//*[#Header]");
Using xml linq. Code is prints any Grid elements that have children with Header attributes.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication7
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> headers = doc.Descendants("Grid").Where(x => x.Elements().Where(y => y.Attribute("Header") != null).Any()).ToList();
}
}
}

Parsing SOAP XML with XDocument

I work with legacy system (not my design) and it have some data persisted in db as serialized xml (SOAP).
XML was created with SoapFormatter.
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, o);
I can't simply deserialize from SOAP because of versioning problem. Model from which data were created have changed and deserialization of persisted data (in xml) is not possible. So I'm trying to figure out how to manually "deserialize" old SOAP to existing model.
I can load it into XDocument and then extract node values with LINQ. But I have problem with Guid values. They are stored in in SOAP XML like this:
<someId xsi:type="a2:Guid" xmlns:a2="http://schemas.microsoft.com/clr/ns/System">
<_a>1396006029</_a>
<_b>2720</_b>
<_c>20328</_c>
<_d>162</_d>
<_e>217</_e>
<_f>181</_f>
<_g>57</_g>
<_h>113</_h>
<_i>92</_i>
<_j>64</_j>
<_k>35</_k>
</someId>
Is there any way to do it painless?
I can read them one by one like this:
var someId = xdoc.Descendants(ns + "root").Elements("someId").Elements("_a").Value;
and try to parse to Guid but it doesn't look nice.
Thanks,
Mike
I added <Root xmlns:xsi="abc"> to xml because the xsi namespace wan't defined.
Try code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication28
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Dictionary<string, int> dict = new Dictionary<string, int>();
XDocument doc = XDocument.Load(FILENAME);
XElement someId = doc.Descendants("someId").FirstOrDefault();
dict = someId.Elements().GroupBy(x => x.Name.LocalName, y => (int)y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
}
}
}

Categories

Resources