Reputation: 85
Is it possible to convert the following XML to List?
<?xml version="1.0" encoding="UTF-8"?>
<DATA>
<SIGNATURES>
<SIGNATURE>
<UTILISATEUR>John Doe</UTILISATEUR>
<ACTEUR>Emetteur</ACTEUR>
<DATE>20160429</DATE>
</SIGNATURE>
<SIGNATURE>
<UTILISATEUR>Philippe Martin</UTILISATEUR>
<ACTEUR>Responsable Qualité Projet</ACTEUR>
<DATE>20160503</DATE>
</SIGNATURE>
</SIGNATURES>
</DATA>
I am looking for the following result:
But the XML is an example, I do not know the structure in advance so I can not create a class that would have the same structure ... I'm looking for a generic solution.
Thanks.
edit:
I wanted to describe a simple case that I would have adapted but in fact, currently I do not use this XML format. He is like this:
<DATA>
<ELEMENTS Cle="NAME_1">
<ELEMENT>
<ELEMENT Cle="TAG_1" Valeur="John Doe"></ELEMENT>
<ELEMENT Cle="TAG_2" Valeur="6 rue du Marché"></ELEMENT>
<ELEMENT Cle="TAG_3" Valeur="Responsable marketing"></ELEMENT>
<ELEMENT Cle="TAG_N" Valeur="..."></ELEMENT>
</ELEMENT>
<ELEMENT>...</ELEMENT>
</ELEMENTS>
<ELEMENTS Cle="NAME_N">...</ELEMENTS>
</DATA>
it "respects" a format but the content is never the same. And I extract the data into some dictionary:
public class Element
{
public string Valeur { get; set; }
public Dictionary<string, Dictionary<string, List<Element>>> taElements { get; set; }
public Element()
{
taElements = new Dictionary<string, Dictionary<string, List<Element>>>();
}
public void SetXML(string xml)
{
var document = XDocument.Parse(xml);
var root = document.Root;
foreach (var elements in root.Elements("ELEMENTS"))
{
var _taElement = new Dictionary<string, List<Element>>();
foreach (var element in elements.Descendants("ELEMENT"))
{
if (element.Attribute("Cle") == null) { continue; }
if (!_taElement.ContainsKey(element.Attribute("Cle").Value)) { _taElement.Add(element.Attribute("Cle").Value, new List<Element>()); }
var elem = new Element();
if (element.Attribute("Valeur") != null) { elem.Valeur = element.Attribute("Valeur").Value; }
_taElement[element.Attribute("Cle").Value].Add(elem);
if (!taElements.ContainsKey(elements.Attribute("Cle").Value)) { taElements.Add(elements.Attribute("Cle").Value, new Dictionary<string, List<Element>>()); }
taElements[elements.Attribute("Cle").Value] = _taElement;
}
}
}
}
But impossible to do Binding of the dictionary in an ItemsControl (which is my final goal).
Upvotes: 1
Views: 120
Reputation: 26917
You can create a List<Dictionary<string,string>>
that will handle most any XML using LINQ to XML. You can extract the name of the element.
var xd = XDocument.Parse(doc);
var elementName = xd.FirstChild().Name.ToString().TrimEnd('S');
var ans = xd.Descendants(elementName).Select(d => d.Descendants().ToDictionary(dd => dd.Name.ToString(), dd => dd.Value)).ToList();
If you need to bind the ans
to a DataGridView
, then you can use a DataTable
.
Using an extension method, you can convert the List<Dictionary>
to a DataTable
:
public static DataTable ToDataTable(this IEnumerable<IDictionary<string, string>> rows) {
var dt = new DataTable();
if (rows.Any()) {
foreach (var kv in rows.First())
dt.Columns.Add(kv.Key, typeof(String));
foreach (var r in rows)
dt.Rows.Add(r.Values.ToArray());
}
return dt;
}
Now you can create a DataTable
for a DataSource
:
var dt = ans.ToDataTable();
Upvotes: 0
Reputation:
Take a look at the XMLSerializer/Deserialize for documentation. It will serialize a class out to XML, or read an XML stream into a class. XML Serialization
static void Main(string[] args)
{
DATA data = new DATA();
data.SIGNATURES = new List<SIGNATURE>();
data.SIGNATURES.Add(new SIGNATURE() { ACTEUR = "", DATE= "", UTILISATEUR= "" });
data.SIGNATURES.Add(new SIGNATURE() { ACTEUR = "", DATE = "", UTILISATEUR = "" });
XmlSerializer serializer = new XmlSerializer(typeof(DATA));
using (TextWriter writer = new StreamWriter(@"Xml.xml"))
{
serializer.Serialize(writer, data);
}
XmlSerializer deserializer = new XmlSerializer(typeof(DATA));
TextReader reader = new StreamReader(@"myXml.xml");
object obj = deserializer.Deserialize(reader);
DATA XmlData = (DATA)obj;
reader.Close();
}
public class SIGNATURE
{
public string UTILISATEUR { get; set; }
public string ACTEUR { get; set; }
public string DATE { get; set; }
}
public class DATA
{
public List<SIGNATURE> SIGNATURES { get; set; }
}
Upvotes: 1