How to deserialize a numbered array of XML elements - c#

I need to deserialize the following XML:
<TIMEWINDOWS>
<NUMBER>10</NUMBER>
<NO0>
<FROM>22-11-2013 08:00:00</FROM>
<TO>22-11-2013 11:59:00</TO>
</NO0>
<NO1>
<FROM>22-11-2013 12:00:00</FROM>
<TO>22-11-2013 15:59:00</TO>
</NO1>
<NO2>
<FROM>23-11-2013 08:00:00</FROM>
<TO>23-11-2013 11:59:00</TO>
</NO2>
<NO3>
<FROM>23-11-2013 12:00:00</FROM>
<TO>23-11-2013 15:59:00</TO>
</NO3>
...
</TIMEWINDOWS>
The output that I require is a collection (list, array, whatever) of TimeWindow objects, for example:
public class TimeWindow
{
public string From { get; set; }
public string To { get; set; }
}
Is there a standard way to handle the NO0, NO1, NO2, ... elements?
I can always build my own parser, but I would much prefer to use a standard approach, such as System.Xml.Serialization.XmlSerializer.

You could use LINQ to XML. Something like...
XDocument doc = XDocument.Load("XMLFile1.xml");
var result = new List<TimeWindow>();
foreach (XElement s in doc.Elements().Descendants())
{
if (s.Name.ToString().StartsWith("NO"))
{
var tw = new TimeWindow {From = (string)s.Element("FROM"),
To = (string)s.Element("TO")};
result.Add(tw);
}
}
You'd probably want to add some checking for nulls around the FROM and TO elements to ensure they are present in the data.

The format of this is quite crazy. Unfortunately this means you will need to parse the xml manually with XDocument or XmlDocument. Lets use the former as it is easier:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Xmlarrayload
{
class Program
{
static void Main(string[] args)
{
var document = XDocument.Parse(#"<TIMEWINDOWS>
<NUMBER>4</NUMBER>
<NO0>
<FROM>22-11-2013 08:00:00</FROM>
<TO>22-11-2013 11:59:00</TO>
</NO0>
<NO1>
<FROM>22-11-2013 12:00:00</FROM>
<TO>22-11-2013 15:59:00</TO>
</NO1>
<NO2>
<FROM>23-11-2013 08:00:00</FROM>
<TO>23-11-2013 11:59:00</TO>
</NO2>
<NO3>
<FROM>23-11-2013 12:00:00</FROM>
<TO>23-11-2013 15:59:00</TO>
</NO3>
</TIMEWINDOWS>");
int number = int.Parse(document.Root.Element("NUMBER").Value);
TimeWindow[] windows = (TimeWindow[])Array.CreateInstance(typeof(TimeWindow), number);
for (int i = 0; i < number; i++)
{
var element = document.Root.Element(string.Format("NO{0}", i));
TimeWindow window = new TimeWindow
{
//it is extremely important to use the correct culture (invariant) to parse the dates.
To = DateTime.ParseExact(element.Element("TO").Value, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat),
From = DateTime.ParseExact(element.Element("FROM").Value, "dd-MM-yyyy HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat)
};
windows[i] = window;
}
}
}
public class TimeWindow
{
public DateTime From { get; set; }
public DateTime To { get; set; }
}
}

A possibility is to do the following:
public class TimeWindow
{
public int number{get;set;}
public Times NO0 = new Times();
public Times NO1 = new Times();
public Times NO2 = new Times();
public Times NO3 = new Times();
}
public class Times()
{
public string FROM{get;set;}
public string TO{get;set;}
}
And if you have this class and help class, you can simply do the following (in another class of course):
XmlSerializer serializer = new XmlSerializer(typeof(TimeWindow));
TimeWindow timeWindow = (TimeWindow)serializer.Deserialize(new StreamReader(pathToFile));
After this, you can access the (at present time "string"-formatted) data via
timeWindow.NO0.FROM;
For me, this worked some days ago.
But I just wrote it from my mind.
//EDIT
Sorry, I didn't realize that there are different numbers of "NOx"-Tags.
This example here works only, id you know the exact amount of those tags.

There is no standard way to handle elements with different names. Because your xml is not standard xml. All children of same type should have same names otherwise they considered as different elements. Additional information (like index of window) should be provided via attributes or elements of child, not via element name:
<TimeWindows number="10"> <!-- actually you don't need number attribute here -->
<TimeWindow index="1">
<From>22-11-2013 08:00:00</From>
<To>22-11-2013 11:59:00</To>
</TimeWindow>
<TimeWindow index="2">
<From>22-11-2013 12:00:00</From>
<To>22-11-2013 15:59:00</To>
</TimeWindow>
<TimeWindow index="3">
<From>23-11-2013 08:00:00</From>
<To>23-11-2013 11:59:00</To>
</TimeWindow>
</TimeWindows>
So, you should handle this manually, e.g. by filtering out <NUMBER> element and just enumerating all other elements
var xdoc = XDocument.Load(path_to_xml);
var windows = xdoc.Root.Elements().Where(e => e.Name.LocalName != "NUMBER")
.Select(n => new TimeWindow {
From = (string)n.Element("FROM"),
To = (string)n.Element("TO")
}).ToList();
Also consider to use DateTime properties in your TimeWindow class, because they hold dates.

The way that I used for solving this problem of mine was saving them to .xml files and retrieved from the .xml file. Check the below code:
private void SaveTimeWindow(TimeWindow[] time, string filePath)
{
//Open a file stream
System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
// Create a xml Serializer object
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(TimeWindow[]));
xmlSer.Serialize(fs, time);
// Close the file stream
fs.Close();
}
For loading you may use the below:
private static TimeWindow[] LoadTime(string filePath)
{
//Open the XML file
if (System.IO.File.Exists(filePath))
{
System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open);
// First create a xml Serializer object
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(TimeWindow[]));
// Deserialize the Matrix object
TimeWindow[] time= (TimeWindow[])xmlSer.Deserialize(fs);
// Close the file stream
fs.Close();
return time;
}
else
{
return null;
}
}
Then you may save your XML based on:
SaveTimeWindow(TimeWindow, yourPath);
and Load it based on:
TimeWindow[] t = LoadTime(yourPath);

Related

C# : Deserialize xml with an unknow number of attributes

I would like to deserialize xml files with the following pattern :
I would like to put the data into a class call Parameter. However, as you can see, I don't knwo by advance how many <Device> I get between <Parameters> ... </Parameters> and the deserialization is not possible with such a DeserializeObjectXMLFile method.
public static Parameters DeserializeObjectXMLFile(String fileToRead)
{
try
{
Parameters parameters = null;
XmlSerializer xs = new XmlSerializer(typeof(Parameters));
using (StreamReader sr = new StreamReader(fileToRead))
{
parameters = xs.Deserialize(sr) as Parameters;
}
return parameters;
}
catch (Exception ex)
{
Logger.Error(ex);
throw ex;
}
}
I imagined having a property List<Device> Devices {get; set} in my Parameters class but deserialization won't work and I don't know how I can do it.
Could you help me in finding a solution ?
Best regards.
RĂ©mi
Use the XmlDocument object in the System.Xml namespace to parse the XML instead of serializing it.
Here is an example:
var xDoc = new System.Xml.XmlDocument();
xDoc.Load(pathToXml);
foreach (System.Xml.XmlNode node in xDoc.DocumentElement.ChildNodes)
{
var attrName = node.Attributes[0].Name;
var attrValue = node.Attributes[0].Value;
Device dev = new Device(attrName, attrValue);
deviceList.Add(dev);
}
While parsing you can then create a new instance of Parameters and add it to a List object.

How to create an XML file via the following XSD

Based on the Schema i'm supposed to build an XML File looking exactly like the XML File i show below, i'm not able to change the structure or anything about it.
<?xml version="1.0" encoding="utf-8"?>
<xsozial-ba xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Mod0>
<M0_1 KnZ="27.92">99079</M0_1>
<M0_2 KnZ="2.55">72</M0_2>
<M0_3 KnZ="8.88">XSozial-BA-SGBII-Version-4.7.0</M0_3>
<M0_4 KnZ="42.7">B</M0_4>
<M0_5 KnZ="43.3">2?"i#+O** Q").9</M0_5>
<M0_6 KnZ="01.5">1993-12</M0_6>
<M0_7 KnZ="2.50">2</M0_7>
<M0_8 KnZ="6.4">1991-10-15T07:49:42.41</M0_8>
<M0_9 KnZ="5.7">string</M0_9>
<M0_10 KnZ="0.2">string</M0_10>
<M0_11 KnZ="96.31">string</M0_11>
</Mod0>
<Mod1>
<M1_3 KnZ="4.39">1972-03-15T01:07:11.07</M1_3>
<M1_4 KnZ="7.9">2018-06-23</M1_4>
<M1_5 KnZ="79.9">1990-09-20</M1_5>
<M1_6 KnZ="2.5">3073880</M1_6>
<M1_8 KnZ="60.2">4130920</M1_8>
<M1_9 KnZ="1.9">336810</M1_9>
<M1_10 KnZ="69.94">4515090</M1_10>
<M1_12 KnZ="40.91">-4127340</M1_12>
<M1_19 KnZ="1.40">858060</M1_19>
<M1_32 KnZ="55.38">4615830</M1_32>
<M1_34 KnZ="73.56">210160</M1_34>
<M1_35 KnZ="9.08">-3908580</M1_35>
<M1_36 KnZ="9.9">-2980490</M1_36>
<M1_37 KnZ="8.3">2025480</M1_37>
<M1_38 KnZ="90.9">-2365230</M1_38>
<M1_39 KnZ="9.80">4466820</M1_39>
<M1_40 KnZ="5.37">519040</M1_40>
<M1_41 KnZ="37.92">872340</M1_41>
<M1_42 KnZ="02.82">2558650</M1_42>
<M1_43 KnZ="4.12">1821630</M1_43>
<M1_44 KnZ="23.7">2068090</M1_44>
<M1_45 KnZ="8.62">2416020</M1_45>
<M1_46 KnZ="57.25">-1816340</M1_46>
<M1_47 KnZ="93.79">-4509440</M1_47>
<M1_48 KnZ="6.50">4405600</M1_48>
<M1_49 KnZ="6.5">-235070</M1_49>
<M1_50 KnZ="0.72">string</M1_50>
<M1_51 KnZ="07.04">string</M1_51>
</Mod1>
<Mod2>
<M2_1 KnZ="7.84">81788BG1441265</M2_1>
<M2_25 KnZ="48.7">string</M2_25>
<M2_3 KnZ="5.09">7</M2_3>
<M2_4 KnZ="4.3">2018-05-17T09:18:32.82</M2_4>
<M2_7 KnZ="0.49">1997-12-15</M2_7>
<M2_10 KnZ="17.8">2011-05-21</M2_10>
<M2_11 KnZ="79.0">78</M2_11>
<M2_12 KnZ="54.5">9</M2_12>
<M2_13 KnZ="59.3">6</M2_13>
<M2_14 KnZ="61.0">16</M2_14>
<M2_16 KnZ="01.23">532616.23</M2_16>
<M2_17 KnZ="0.3">696766.23</M2_17>
<M2_18 KnZ="10.73">789585.23</M2_18>
<M2_26 KnZ="70.8">2010-03-05</M2_26>
<M2_27 KnZ="09.3">2005</M2_27>
<M2_28 KnZ="1.49">743031.23</M2_28>
<M2_29 KnZ="3.18">172483.23</M2_29>
<M2_30 KnZ="7.59">684711.23</M2_30>
<M2_31 KnZ="3.16">string</M2_31>
<M2_32 KnZ="8.27">string</M2_32>
</Mod2>
<Mod3>
<M3_1 KnZ="86.2">2234138078</M3_1>
<M3_2 KnZ="7.0">46048BG6406738</M3_2>
<M3_34 KnZ="9.7">string</M3_34>
<M3_3 KnZ="56.6">9</M3_3>
<M3_4 KnZ="71.47">1994-07-12T21:35:55.77</M3_4>
<M3_5 KnZ="92.33">string</M3_5>
<M3_6 KnZ="8.4">string</M3_6>
<M3_7 KnZ="3.40">string</M3_7>
<M3_8 KnZ="46.0">string</M3_8>
<M3_9 KnZ="0.8">string</M3_9>
<M3_10 KnZ="4.26">ABC</M3_10>
<M3_11 KnZ="82.07">string</M3_11>
<M3_12 KnZ="27.15">string</M3_12>
<M3_13 KnZ="55.42">73388</M3_13>
<M3_14 KnZ="62.55">string</M3_14>
<M3_18 KnZ="5.3">1992-01-03</M3_18>
<M3_19 KnZ="9.5">W</M3_19>
<M3_20 KnZ="5.2">hv_1Zv_cR7_2</M3_20>
<M3_21 KnZ="89.05">132</M3_21>
<M3_22 KnZ="5.34">4</M3_22>
<M3_24 KnZ="45.4">4</M3_24>
<M3_26 KnZ="7.4">9</M3_26>
<M3_29 KnZ="90.05">false</M3_29>
<M3_35 KnZ="05.4">03</M3_35>
<M3_36 KnZ="18.89">true</M3_36>
<M3_37 KnZ="77.28">1</M3_37>
<M3_38 KnZ="38.6">77</M3_38>
<M3_39 KnZ="09.71">7</M3_39>
<M3_40 KnZ="7.5">1</M3_40>
<M3_41 KnZ="5.9">9</M3_41>
<M3_43 KnZ="25.54">5</M3_43>
<M3_45 KnZ="81.3">string</M3_45>
<M3_46 KnZ="6.2">string</M3_46>
</Mod3>
<Mod4>
<M4_1 KnZ="04.67">516C002312</M4_1>
<M4_2 KnZ="8.27">85358BG1042986</M4_2>
<M4_9 KnZ="9.7">string</M4_9>
<M4_3 KnZ="69.1">6</M4_3>
<M4_4 KnZ="49.60">1998-06-12T06:22:53.10</M4_4>
<M4_5 KnZ="2.4">438</M4_5>
<M4_6 KnZ="81.8">226308.23</M4_6>
<M4_7 KnZ="35.45">1991-06-01</M4_7>
<M4_8 KnZ="41.8">1988-09-26</M4_8>
<M4_10 KnZ="1.66">string</M4_10>
<M4_11 KnZ="8.93">string</M4_11>
</Mod4>
<Mod5>
<M5_1 KnZ="82.9">8398640296</M5_1>
<M5_2 KnZ="64.2">98431BG8790232</M5_2>
<M5_9 KnZ="2.1">string</M5_9>
<M5_3 KnZ="0.0">6</M5_3>
<M5_4 KnZ="62.4">2019-03-22T15:17:14.43</M5_4>
<M5_5 KnZ="20.04">145</M5_5>
<M5_6 KnZ="6.93">70433.23</M5_6>
<M5_10 KnZ="36.4">58</M5_10>
<M5_11 KnZ="40.8">126736.23</M5_11>
<M5_13 KnZ="33.30">string</M5_13>
<M5_14 KnZ="5.73">string</M5_14>
</Mod5>
<Mod7>
<M7_1 KnZ="82.1">423_519620</M7_1>
<M7_2 KnZ="03.0">48032BG3955047</M7_2>
<M7_12 KnZ="5.2">string</M7_12>
<M7_3 KnZ="21.14">8</M7_3>
<M7_4 KnZ="84.42">2002-09-12T07:42:56.87</M7_4>
<M7_6 KnZ="56.4">565598.23</M7_6>
<M7_8 KnZ="9.03">10</M7_8>
<M7_9 KnZ="4.1">988534.23</M7_9>
<M7_10 KnZ="1.2">766323.23</M7_10>
<M7_14 KnZ="0.4">268945.23</M7_14>
<M7_15 KnZ="4.7">36217.23</M7_15>
<M7_16 KnZ="71.22">string</M7_16>
<M7_17 KnZ="63.8">string</M7_17>
</Mod7>
<Mod8>
<M8_1 KnZ="77.31">915B189370</M8_1>
<M8_2 KnZ="2.9">11439BG3859455</M8_2>
<M8_10 KnZ="66.17">string</M8_10>
<M8_3 KnZ="5.0">4</M8_3>
<M8_4 KnZ="63.5">1996-03-28T14:55:21.87</M8_4>
<M8_6 KnZ="9.02">318</M8_6>
<M8_7 KnZ="5.12">955557.23</M8_7>
<M8_8 KnZ="57.4">2018-03-05</M8_8>
<M8_9 KnZ="89.8">1977-04-08</M8_9>
<M8_11 KnZ="48.5">string</M8_11>
<M8_12 KnZ="7.33">string</M8_12>
<M8_13 KnZ="52.4">string</M8_13>
</Mod8>
<Mod10>
<M10_1 KnZ="78.54">820m873680</M10_1>
<M10_20 KnZ="5.27">string</M10_20>
<M10_4 KnZ="00.84">1998-01-21T15:54:38.32</M10_4>
<M10_5 KnZ="83.6">5</M10_5>
<M10_6 KnZ="86.0">2005-10-09</M10_6>
<M10_7 KnZ="7.9">2002-06-03</M10_7>
<M10_8 KnZ="47.19">15</M10_8>
<M10_9 KnZ="30.45">97</M10_9>
<M10_10 KnZ="2.1">1974</M10_10>
<M10_13 KnZ="77.65">false</M10_13>
<M10_16 KnZ="69.44">1987-06-19</M10_16>
<M10_21 KnZ="2.6">8</M10_21>
<M10_23 KnZ="0.31">7</M10_23>
<M10_28 KnZ="36.20">40158938</M10_28>
<M10_29 KnZ="3.2">95338014</M10_29>
<M10_30 KnZ="2.0">1993-03-20T00:55:27.15</M10_30>
<M10_31 KnZ="67.5">2</M10_31>
<M10_32 KnZ="0.13">true</M10_32>
<M10_33 KnZ="7.06">7</M10_33>
<M10_34 KnZ="10.34">string</M10_34>
<M10_35 KnZ="10.35">string</M10_35>
</Mod10>
<Mod11>
<M11_1 KnZ="80.33">074l382106</M11_1>
<M11_11 KnZ="8.2">string</M11_11>
<M11_4 KnZ="3.21">2005-01-22T01:35:47.34</M11_4>
<M11_5 KnZ="05.4">1998-11-08</M11_5>
<M11_6 KnZ="9.55">2011-10-28</M11_6>
<M11_7 KnZ="2.14">5</M11_7>
<M11_10 KnZ="64.93">54</M11_10>
<M11_14 KnZ="14.42">87447767</M11_14>
<M11_15 KnZ="52.15">17</M11_15>
<M11_16 KnZ="11.56">1996-06-03T03:46:31.43</M11_16>
<M11_17 KnZ="52.0">false</M11_17>
<M11_18 KnZ="43.66">string</M11_18>
<M11_19 KnZ="1.4">string</M11_19>
</Mod11>
<Mod12>
<M12_1 KnZ="59.48">711H885079</M12_1>
<M12_15 KnZ="20.78">string</M12_15>
<M12_4 KnZ="74.21">1982-09-23T12:16:04.42</M12_4>
<M12_5 KnZ="9.6">1</M12_5>
<M12_10 KnZ="45.25">0</M12_10>
<M12_16 KnZ="3.1">2</M12_16>
<M12_17 KnZ="6.8">5</M12_17>
<M12_18 KnZ="9.7">true</M12_18>
<M12_19 KnZ="0.3">string</M12_19>
<M12_20 KnZ="97.5">string</M12_20>
</Mod12>
<Mod13>
<M13_1 KnZ="0.75">738D383042</M13_1>
<M13_33 KnZ="6.6">string</M13_33>
<M13_4 KnZ="66.29">2006-11-24T12:58:05.00</M13_4>
<M13_5 KnZ="2.79">1990-01-28</M13_5>
<M13_7 KnZ="1.6">1981-02-13</M13_7>
<M13_8 KnZ="3.76">2067</M13_8>
<M13_10 KnZ="36.9">50</M13_10>
<M13_12 KnZ="5.6">09845139</M13_12>
<M13_13 KnZ="47.61">421479.23</M13_13>
<M13_16 KnZ="61.4">5</M13_16>
<M13_35 KnZ="86.95">string</M13_35>
<M13_36 KnZ="1.0">28</M13_36>
<M13_37 KnZ="12.4">1998-07-21T04:31:32.86</M13_37>
<M13_38 KnZ="6.8">79296731</M13_38>
<M13_39 KnZ="80.56">7</M13_39>
<M13_40 KnZ="63.8">string</M13_40>
<M13_41 KnZ="48.7">string</M13_41>
</Mod13>
<Mod14>
<M14_1 KnZ="6.4">944c687231</M14_1>
<M14_18 KnZ="88.8">string</M14_18>
<M14_4 KnZ="71.28">1994-07-11T02:46:34.93</M14_4>
<M14_7 KnZ="34.1">57</M14_7>
<M14_14 KnZ="4.1">1980-07-27</M14_14>
<M14_15 KnZ="03.8">1972-02-06</M14_15>
<M14_16 KnZ="9.9">2008-04-02</M14_16>
<M14_17 KnZ="1.7">1988-05-03</M14_17>
<M14_19 KnZ="76.5">string</M14_19>
<M14_20 KnZ="8.56">string</M14_20>
</Mod14>
<Mod15>
<M15_1 KnZ="5.24">2016-03-10T11:18:31.47</M15_1>
<M15_4 KnZ="2.1">1330</M15_4>
<M15_5 KnZ="74.7">4850</M15_5>
<M15_6 KnZ="52.74">94</M15_6>
<M15_7 KnZ="9.5">4124</M15_7>
<M15_8 KnZ="14.2">string</M15_8>
<M15_9 KnZ="00.11">1981-08-07</M15_9>
<M15_10 KnZ="79.0">1982-09-11</M15_10>
<M15_11 KnZ="51.7">52</M15_11>
<M15_15 KnZ="53.41">99914</M15_15>
<M15_16 KnZ="56.31">string</M15_16>
<M15_17 KnZ="54.72">string</M15_17>
<M15_18 KnZ="91.12">69730972</M15_18>
<M15_19 KnZ="81.7">string</M15_19>
<M15_20 KnZ="7.6"></M15_20>
<M15_21 KnZ="59.27">79995</M15_21>
<M15_22 KnZ="16.93">string</M15_22>
<M15_23 KnZ="82.7">7</M15_23>
<M15_24 KnZ="6.9">659</M15_24>
<M15_26 KnZ="37.4">11</M15_26>
<M15_27 KnZ="2.2">719</M15_27>
<M15_28 KnZ="76.59">810</M15_28>
<M15_29 KnZ="2.01">9179</M15_29>
<M15_30 KnZ="2.57">5401</M15_30>
<M15_31 KnZ="98.92">1981-04-21T16:37:08.82</M15_31>
<M15_32 KnZ="7.93">32376237</M15_32>
<M15_33 KnZ="9.97">string</M15_33>
<M15_34 KnZ="8.95">string</M15_34>
</Mod15>
<Mod16>
<M16_1 KnZ="7.5">2008-05-06T13:35:51.13</M16_1>
<M16_2 KnZ="5.2">7</M16_2>
<M16_3 KnZ="6.8">4</M16_3>
<M16_4 KnZ="9.0">8</M16_4>
<M16_5 KnZ="0.1">7</M16_5>
<M16_6 KnZ="36.9">46</M16_6>
<M16_7 KnZ="5.9">11</M16_7>
<M16_8 KnZ="1.05">9791</M16_8>
<M16_9 KnZ="94.20">string</M16_9>
<M16_10 KnZ="71.3">string</M16_10>
</Mod16>
<Mod17>
<M17_1 KnZ="40.88">361x328583</M17_1>
<M17_3 KnZ="37.1">string</M17_3>
<M17_4 KnZ="7.26">2015-02-15T18:24:22.56</M17_4>
<M17_5 KnZ="0.4">string</M17_5>
<M17_6 KnZ="0.27">2010-05-18</M17_6>
<M17_7 KnZ="3.13">1977-08-26</M17_7>
<M17_8 KnZ="6.8">string</M17_8>
<M17_9 KnZ="0.9">string</M17_9>
</Mod17>
<Mod18>
<M18_1 KnZ="7.60">891_193121</M18_1>
<M18_2 KnZ="8.81">48213BG9962640</M18_2>
<M18_3 KnZ="1.29">string</M18_3>
<M18_4 KnZ="1.84">1981-11-10T04:34:42.14</M18_4>
<M18_6 KnZ="2.3">574003.23</M18_6>
<M18_7 KnZ="1.69">716121.23</M18_7>
<M18_8 KnZ="2.9">244879.23</M18_8>
<M18_9 KnZ="7.7">995622.22</M18_9>
<M18_10 KnZ="10.76">480830.23</M18_10>
<M18_11 KnZ="29.96">537223.23</M18_11>
<M18_12 KnZ="8.9">315441.23</M18_12>
<M18_13 KnZ="58.63">830201.23</M18_13>
<M18_14 KnZ="11.3">784861.23</M18_14>
<M18_15 KnZ="8.1">617589.23</M18_15>
<M18_16 KnZ="5.15">655490.23</M18_16>
<M18_17 KnZ="22.2">397393.23</M18_17>
<M18_18 KnZ="6.9">299696.23</M18_18>
<M18_19 KnZ="62.93">584218.23</M18_19>
<M18_20 KnZ="75.3">string</M18_20>
<M18_21 KnZ="2.72">string</M18_21>
</Mod18>
</xsozial-ba>
What i did is to use the xsd.exe Tool like in this explanation to create a class from the XSD that i have: Generating XML file using XSD file
Now i got my class without having to code it myself. But.. how do i code the Serialization now? Is that even possible because the element names are dynamic? And if it is, how?
You need to create an instance of the root class (xsozial-ba) and add values to the instance. The class structure is not dynamic, only the values. The serializer code would look like this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
xsozial_ba xsozial_ba = new xsozial_ba()
{
Mod0 = new Mod0()
{
M0_1 = new M0_1() { KnZ = 27.92M, value = "99079" }
}
};
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(xsozial_ba));
serializer.Serialize(writer, xsozial_ba);
}
}
[XmlRoot(ElementName = "xsozial-ba")]
public class xsozial_ba
{
public Mod0 Mod0 { get; set; }
}
public class Mod0
{
public M0_1 M0_1 { get; set; }
}
public class M0_1
{
[XmlAttribute()]
public decimal KnZ { get; set; }
[XmlText]
public string value { get; set; }
}
}

LINQ XML Get value of element from multiple where statement

First question on SO, apologies if I mess some of this up. I'm new to c# and LINQ and have spent the past 2 days searching SO for a solution, none seem to be exactly what I'm after. So...
The xml file I'm querying is generated from a DICOM Structured Report file. I'm trying to get specific values of elements from this xml file. These elements correspond to specific measurements that were taken during an ultrasound examination. The entire xml file is 15k lines long so for simplicity I've edited it. I'll just show one example of what I'm trying to do but the process will be the same for all other elements I'm looking to get.
The element I want to get has to meet 3 criteria, in this case Tricuspid Valve, Peak Velocity and Regurgitant Flow but this changes depending on the measurement that was taken. Once those criteria are met I want to get the value of , which in this case is 2120.
The xml
<report type="Comprehensive SR">
<document>
<content>
<container flag="SEPARATE">
<container flag="SEPARATE">
<code>
<meaning>Tricuspid Valve</meaning>
</code>
<container flag="SEPARATE">
<num>
<concept>
<meaning>Peak Velocity</meaning>
</concept>
<code>
<meaning>Regurgitant Flow</meaning>
</code>
<value>2120</value>
<unit>
<value>mm/s</value>
</unit>
</num>
My code in c#
XDocument xmlSR = XDocument.Load("DICOMSRtest.xml");
var TRVmax = from c in xmlSR.Descendants("container")
where (string)c.Element("code").Element("meaning") == "Tricuspid Valve"
where (string)c.Element("concept").Element("meaning") == "Peak Velocity"
where (string)c.Element("code").Element("meaning") == "Regurgitant Flow"
select c.Element("container").Element("num").Element("value");
Console.Write("TRVmax: " + TRVmax);
When I run the code I get the following
TRVmax: System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.Xml.Linq.XElement]
Any help or direction to some documentation which I can read to solve this would be greatly appreciated.
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
{
static void Main(string[] args)
{
XDocument doc = XDocument.Load("PurchaseOrder.xml");
List<XElement> xContainers = doc.Descendants("container").Where(x => x.Element("num") != null).ToList();
List<Container> containers = new List<Container>();
foreach (XElement xContainer in xContainers)
{
Container newContainer = new Container();
containers.Add(newContainer);
newContainer.code = (string)xContainer.Descendants("code").FirstOrDefault();
newContainer.concept = (string)xContainer.Descendants("concept").FirstOrDefault();
newContainer.value = (int)xContainer.Descendants("value").FirstOrDefault();
newContainer.unit = (string)xContainer.Descendants("unit").FirstOrDefault();
}
}
}
public class Container
{
public string code { get; set; }
public string concept { get; set; }
public int value { get; set; }
public string unit { get; set; }
}
}

How to make serialized data compact?

i wrote an application which is a custom console that allows execution of various commands. One of the commands allows serialization of data. The input data is a string, which is a list of comma separated values.
My question is - how to make the serialized data compact as much as possible?
The serialization format is not important for me.
Here is the command's code:
using CustomConsole.Common;
using System.IO;
using System.Xml.Serialization;
using System;
namespace Shell_Commander.Commands
{
public class SerializeCommand : ICommand
{
private string _serializeCommandName = "serialize";
public string Name { get { return this._serializeCommandName; } set { _serializeCommandName = value; } }
public string Execute(string parameters)
{
try
{
var splittedParameters = parameters.Split(" ");
var dataToSerialize = splittedParameters[0].Split(",");
var pathTofile = splittedParameters[1].Replace(#"\", #"\\");
XmlSerializer serializer = new XmlSerializer(dataToSerialize.GetType());
using (StreamWriter writer = new StreamWriter(pathTofile))
{
serializer.Serialize(writer, dataToSerialize);
var length = new FileInfo(pathTofile).Length;
Console.WriteLine($"Wrote file to: {pathTofile}");
return length.ToString();
}
}
catch (Exception e)
{
Console.WriteLine(e);
return "0";
}
}
}
}
The command accepts 2 parameters:
Data to serialize
File path (in order to save the serialized data).
Example - for the "1,2,4" input, the following file will be saved:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>1</string>
<string>2</string>
<string>4</string>
</ArrayOfString>
EDIT:
I want my command to be able to serialize also complex objects in the future, so writing the string as is to the file is not a solution.
I want to use only standard serialization methods and formats.

How to deserialize XML into an object?

I'm trying to convert an XML doc (invoiceList) into an object. Ideally I'd like to convert it into a collection of objects ("Invoices").
Below is a fragment of the XML. I've also included a fragment off my INVOICE object. And finally my attempt at deserialization. The error message I get is so useless that I don't know where to start.
<?xml version="1.0" encoding="utf-8"?>
<invoiceListResponse>
<invoiceList>
<invoiceListItem>
<invoiceUid>39165890</invoiceUid>
<lastUpdatedUid>AAAAADrKwis=</lastUpdatedUid>
<ccy>JPY</ccy>
<autoPopulateFXRate>false</autoPopulateFXRate>
<fcToBcFxRate>1.0000000000</fcToBcFxRate>
<transactionType>S</transactionType>
<invoiceDate>2013-12-26</invoiceDate>
<utcFirstCreated>2013-12-26T08:12:22</utcFirstCreated>
<utcLastModified>2013-12-26T08:12:22</utcLastModified>
<summary />
<invoiceNumber>W101010101</invoiceNumber>
fragment of Invoice object code
[XmlRoot(ElementName = "invoice")]
public class InvoiceDto : TransactionDto
{
public InvoiceDto()
{
TradingTerms = new TradingTermsDto();
QuickPayment = new QuickPaymentDto();
}
public InvoiceDto(string transactionType, string layout)
{
Layout = layout;
TransactionType = transactionType;
TradingTerms = new TradingTermsDto();
QuickPayment = new QuickPaymentDto();
}
[XmlElement(ElementName = "transactionType")]
public string TransactionType;
[XmlElement(ElementName = "invoiceType")]
public string InvoiceType;
[XmlElement(ElementName = "contactUid")]
public int ContactUid;
[XmlElement(ElementName = "shipToContactUid")]
public int ShipToContactUid;
[XmlElement(ElementName = "externalNotes")]
public string ExternalNotes;
My code:
Dim list As XmlDocument = proxy.Find(queries)
'Deserialize text file to a new object.
Using reader As XmlReader = XmlReader.Create(New StringReader(list.InnerXml))
reader.MoveToContent()
reader.Read()
reader.Read()
theinv = DirectCast(New XmlSerializer(GetType(Dto.InvoiceDto)).Deserialize(reader), Dto.InvoiceDto)
Debug.Write(theinv.InvoiceNumber)
Error is:
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.Xml.dll
Additional information: There is an error in XML document (1, 74).
The easiest thing to do is to create a class that matches the entire XML document from its root level down. It doesn't need to contain a property for every node, but it needs to at least contain a property for each element in the path to get from the root element down to the ones that you care about. For instance, the following class will work to load the document in your example:
[XmlRoot("invoiceListResponse")]
public class InvoiceListResponse
{
[XmlArray("invoiceList")]
[XmlArrayItem("invoiceListItem")]
public InvoiceDto[] InvoiceList;
}
Then, you can deserialize into it like this:
XmlSerializer s = new XmlSerializer(typeof(InvoiceListResponse));
using (FileStream f = new FileStream("Test.xml", System.IO.FileMode.Open))
{
InvoiceListResponse response = (InvoiceListResponse)s.Deserialize(f);
}
Edit
Based on your comments, below, it appears that what you need to do is to deserialize into that exact DTO class, without making any modifications to it. If that is the case, and you don't want to create a wrapper class as I demonstrated in my first example, you could always do something like this:
Dim invoices As New List(Of InvoiceDto)()
Dim serializer As New XmlSerializer(GetType(InvoiceDto))
For Each i As XmlNode In doc.SelectNodes("/invoiceListResponse/invoiceList/invoiceListItem")
Using reader As New StringReader("<invoice>" & i.InnerXml & "</invoice>")
invoices.Add(DirectCast(serializer.Deserialize(reader), InvoiceDto))
End Using
Next

Categories

Resources