Converting an XML file to a multi-dimensional dictionnary - c#

I'm trying to import XML files into my C# code.
I would like to access these data like a dictionnary element.
Example:
// XML:
<root>
<node>
<value1>
</value1>
<value2>
<properties>
</properties>
</value2>
<randomnode>
<blabla>X</blabla>
</randomnode>
</node>
</root>
// C#:
values["root"]["node"]["randomnode"]["blabla"] == "X" // true
Is there any way to do this?
As far as I've searched, I could only get a dictionnary using XElements, but it was only 2-dimensions and I had to specify names and values as attributes in the XML file.
Thanks for answering!

I suggest you to use dynamic type for this. See here for code. Or here.

I've used sharpSerializer for that. Heres a pretty good walkthrough:
XML Serialization of Generic Dictionary, Multidimensional Array, and Inherited Type, with sharpSerializer .NET

Related

xpath to return value from xml doc

I'm wondering if there is a way to do the following with one xpath expression:
I have an XML doc similar to this but with many 'results',
<result>
<id>1</id>
<name>joe</name>
</result>
<result>
<id>2</id>
<name>jim</name>
</result>
I'm passing a variable into a C# utility along with the xml, and want to return the name where the id = the variable.
I could loop through the xml until reach what I'm after but if there's a handy xpath way to do it I'm listening...
thanks
Assuming you have a root element in there like "results" that XPath can validate, and that you don't have any other nodes named "result"...
//result[id=1]/name
Or you could get the text outright, instead of it being returned in a node
//result[id=1]/name/text()
And if you want to make sure that there's only one result, you could surround it with parens and put a [1] after
(//result[id=1]/name/text())[1]
I would also recommend testing with one of the xpath test sites out there like this one, but beware that different xpath/xml parsers sometimes behave differently.

How can I deserialize this XML to a useful data structure?

I am working with a receipt format that is returned to me as a "saml assertion". This is a known and well defined format, but on my current platform, I don't have access to libraries that can deserialize the xml to the original classes.
I've determined that I will likely need to roll my own classes but given the format of the xml, I don't really know what the C# classes would look like or the definition and tricks needed to get it to deserialize.
The goal is that from the receipt, create a list of C# objects that I can examine. I would like to retain the value in Format, in the Name node as well as the id. In addition, part of what makes this challenging is that Statement consists of both subject and attribute elements. One of the questions I would like to ask the list is, does the list contain a Assertion that has an Attribute node with "Gamma" having the value of 999.
here's the format:
<Assertion>
<Statement>
<Subject>
<Name Format="http://name.com/123/45/ProductName" Id="123">123456</Name>
</Subject>
<Attribute Name="Alpha">
<Value>111</Value>
</Attribute>
<Attribute Name="Gamma">
<Value>22</Value>
</Attribute>
...
<Attribute Name="Delta">
<Value>3</Value>
</Attribute>
</Statement>
</Assertion>
You can use the XML Schema Definition Tool (Xsd.exe) to get your class structure started.
Here's an excellent blog post by Yogesh Joshi that walks through the whole process: http://blogs.msdn.com/b/yojoshi/archive/2011/05/14/xml-serialization-and-deserialization-entity-classes-with-xsd-exe.aspx
As Kon said in the comment, the Attribute nodes should be wrapped in a container element. I haven't found any good way to deserialize a list that also has other elements in it (or attributes, either). You'll probably be forced to have your class implement IXmlSerializable and write more than you would otherwise need to.

DataContract/DataMember multiple elements in xml

I have an XML like this:
<data>
<foo>some value</foo>
<result>...</result>
<result>...</result>
<result>...</result>
...
</data>
I would like to deserialize it with DataContract/DataMember..
I know how to handle the array/collection of results elements if they were embedded inside a parent object like:
<data>
<foo>some value</foo>
<collectionOfResults>
<result>...</result>
<result>...</result>
<result>...</result>
...
</collectionOfResults>
</data>
But I don't know how to do it without the embedding element. Do you?
If you need to control the format of the XML, then you don't want to use the DataContractSerializer. Use the XML Serializer instead.

How to embed xml in xml

I need to embed an entire well-formed xml document within another xml document. However, I would rather avoid CDATA (personal distaste) and also I would like to avoid the parser that will receive the whole document from wasting time parsing the embedded xml. The embedded xml could be quite significant, and I would like the code that will receive the whole file to treat the embedded xml as arbitrary data.
The idea that immediately came to mind is to encode the embedded xml in base64, or to zip it. Does this sound ok?
I'm coding in C# by the way.
You could convert the XML to a byte array, then convert it to binary64 format. That will allow you to nest it in an element, and not have to use CDATA.
The W3C-approved way of doing this is XInclude. There is an implementation for .Net at http://mvp-xml.sourceforge.net/xinclude/
Just a quick note, I have gone the base64 route and it works just fine but it does come with a stiff performance penalty, especially under heavy usage. We do this with document fragments upto 20MB and after base64 encoding they can take upwards of 65MB (with tags and data), even with zipping.
However, the bigger issue is that .NET base64 encoding can consume up-to 10x the memory when performing the encoding/decoding and can frequently cause OOM exceptions if done repeatedly and/or done on multiple threads.
Someone, on a similar question recommended ProtoBuf as an option, as well as Fast InfoSet as another option.
Depending on how you construct the XML, one way is to not care about it and let the framework handle it.
XmlDocument doc = new XmlDocument();
doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\" ?><helloworld></helloworld>");
string xml = "<how><are><you reply=\"i am fine\">really</you></are></how>";
doc.GetElementsByTagName("helloworld")[0].InnerText = xml;
The output will be something like a HTMLEncoded string:
<?xml version="1.0" encoding="utf-8"?>
<helloworld><how><are><you
reply="i am fine">really</you></are></how>
</helloworld>
I would encode it in your favorite way (e.g. base64 or HttpServerUtility::UrlEncode, ...) and then embed it.
If you don't need the xml declaration (first line of the document), just insert the root element (with all childs) into the tree of the other xml document as a child of an existing element. Use a different namespace to seperate the inserted elements.
It seems that serialization is the recommended method.
Can't you use XSLT for this? Perhaps using xsl:copy or xsl:copy-of? This is what XSLT is for.
I use Comments for this :
<!-- your xml text -->
[EDITED]
If the embedded xml with comments, replace it with a different syntax.
<?xml version="1.0" encoding="iso-8859-1" ?>
<xml>
<status code="0" msg="" cause="" />
<data>
<order type="07" user="none" attrib="..." >
<xmlembeded >
<!--
<?xml version="1.0" encoding="iso-8859-1" ?>
<xml>
<status ret="000 "/>
<data>
<allxml_here />
<!** embedeb comments **>
</data>
<xml>
-->
</xmlembeded >
</order>
<context sessionid="12345678" scriptname="/from/..." attrib="..." />
</data>
</xml>

What's the quickest (code execution) way to execute an XML reading?

I have to read the XML:
<items>
<item>
<prop1>value1</prop1>
<prop2>value2</prop2>
<prop3>value3</prop3>
</item>
<item>
<prop1>value1</prop1>
<prop2>value2</prop2>
<prop3>value3</prop3>
</item>
</items>
And put the values into a List<CLASS>.
Some options:
Use XMLSerializer to deserialize to a List
Use XMLDocument to read each item using SelectNodes with XPath and put the values into a List
Use XMLReader to read each node and put the values into a List
Other option...
By far the fastest that I have seen is to use XSD.exe to create an XSD and Class to go with it, then use serialization.
Another option would be to use LinqToXml.
If you're in dotnet, install the WCF starter pack. Then you'll have an option "Paste XML as Types", so you can cut the XML you're looking to serialize into the clipboard and paste it into code as a serializable type. Then you can just serialize the XML and get the values through the class.

Categories

Resources