Get Each Value on an XML Node - c#

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());
}
}
}

Related

Extracting XML values in multidimensional array c#

I have an xml file as below, and I need to extract values and put them inside a multidimensional array. The idea is, when I have more than one tag <string> per root element <Etiquette>, I need to repeat the same other values with each different value of the tag <string>
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfEtiquette xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Etiquette>
<BgColor>#8075D1C5</BgColor>
<BorderColor>#FF4E5B6F</BorderColor>
<AssociatedAffaireId>
<string>d4689f33-5600-47fe-883d-efcbf5e469c2</string>
<string>1bae35dd-d501-4d87-bdd4-147fc0ba29d2</string>
</AssociatedAffaireId>
<Label>Ouverte</Label>
</Etiquette>
<Etiquette>
<BgColor>#80949CA8</BgColor>
<BorderColor>#FF155E70</BorderColor>
<AssociatedAffaireId>
<string>203cc4a8-8c24-4a2d-837c-29c7c1f73007</string>
</AssociatedAffaireId>
<Label>Fermée</Label>
</Etiquette>
</ArrayOfEtiquette>
Desired result:
{"#8075D1C5","#FF4E5B6F","d4689f33-5600-47fe-883d-efcbf5e469c2","Ouverte"}
{"#8075D1C5","#FF4E5B6F","1bae35dd-d501-4d87-bdd4-147fc0ba29d2","Ouverte"}
{"#80949CA8","#FF155E70","203cc4a8-8c24-4a2d-837c-29c7c1f73007","Fermée"}
Regards,
Using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication157
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("Etiquette")
.SelectMany(x => x.Descendants("string")
.Select(y => new { BgColor = (string)x.Element("BgColor"), BorderColor = (string)x.Element("BorderColor"), UID = (string)y }))
.ToList();
}
}
}
I you want just an array instead of anonymous type use :
new string[] { (string)x.Element("BgColor"), (string)x.Element("BorderColor"), (string)y }
You can try with XDocument
XDocument xdoc = XDocument.Load("XMLFile7.xml");
var mdAarray = xdoc.Descendants("Etiquette")
.SelectMany(etiquette =>
etiquette.Descendants("string")
.Select(associatedaffaire => new string[] {
etiquette.Element("BgColor").Value.ToString(),
etiquette.Element("BorderColor").Value.ToString(),
associatedaffaire.Value.ToString(),
etiquette.Element("Label").Value.ToString() }))
.ToArray();
Console.WriteLine(JsonConvert.SerializeObject(mdAarray));
OUTPUT
[
["#8075D1C5","#FF4E5B6F","d4689f33-5600-47fe-883d-efcbf5e469c2","Ouverte"],
["#8075D1C5","#FF4E5B6F","1bae35dd-d501-4d87-bdd4-147fc0ba29d2","Ouverte"],
["#80949CA8","#FF155E70","203cc4a8-8c24-4a2d-837c-29c7c1f73007","Fermée"]
]
you only need to iterate first on Etiquette then iterate again on AssociatedAffaireId
Each time you can insert inside the array or list (I will use list for simplicity)
XDocument xdoc = XDocument.Load("pathToXml.xml");
// iterate all Etiquette elements
foreach (var etiquette in xdoc.Root.Elements("Etiquette"))
{
// store common values
string bgColor = etiquette.Element("BgColor").Value;
string borderColor = etiquette.Element("BorderColor").Value;
string label = etiquette.Element("Label").Value;
// iterate all AssociatedAffaireId.string elements and add to list
var associatedAffaireIdEl = etiquette.Element("AssociatedAffaireId");
foreach (var associatedAffaireId in associatedAffaireIdEl.Elements("string"))
{
string aaid = associatedAffaireId.Value;
listOfArray.Add(new string[]{bgColor, borderColor, aaid, label});
}
}
I hope this could help.
Sorry I found some errors. Check out my fiddle here.

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());
}
}
}

C# XDocument Read all Nodes from XML-File

I have an XML-file like this:
<Inventory>
<Item>
<Name>Super Mario Bros</Name>
<Count>14</Count>
<Price>29,99</Price>
<Comment><No Comments on this Product></Comment>
<Artist>N/A</Artist>
<Publisher>Nintendo</Publisher>
<Genre>Video Games</Genre>
<Year>1985</Year>
<ProductID>001</ProductID>
</Item>
<Item>
<Name>The Legend of Zelda</Name>
<Count>12</Count>
<Price>34,99</Price>
<Comment><No Comments on this Product></Comment>
<Artist>N/A</Artist>
<Publisher>Nintendo</Publisher>
<Genre>Video Games</Genre>
<Year>1986</Year>
<ProductID>002</ProductID>
</Item>
<Item>
<Name>Street Fighter</Name>
<Count>82</Count>
<Price>19,99</Price>
<Comment><No Comments on this Product></Comment>
<Artist>N/A</Artist>
<Publisher>Nintendo</Publisher>
<Genre>Video Games</Genre>
<Year>1987</Year>
<ProductID>003</ProductID>
</Item>
</Inventory>
(There are more Items, but they are all the same, except for the values.)
Now I want to iterate through each Item and extract every value from each node. Here's what I've tried so far:
var xDocument = XDocument.Load(FilePath_CSVToXML);
string xml = xDocument.ToString();
StringBuilder sb = new StringBuilder();
foreach (XElement xe in xDocument.Descendants("Inventory")) {
sb.Append(xe);
}
Console.WriteLine(sb.ToString());
Console.ReadLine();
The code above properly displays the XML-file, but it keeps the Nodes. (Name, Count, Price, etc.) I only want the values.
You need to use the Value property, i.e. sb.Append(xe.Value).
Try code below. The innertag of Comment doesn't need angle brackets so remove.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication49
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("Item").Select(x => new {
name = (string)x.Element("Name"),
count = (int)x.Element("Count"),
price = (decimal)x.Element("Price"),
comment = (string)x.Element("Comment"),
artist = (string)x.Element("Artist"),
publisher = (string)x.Element("Publisher"),
genre = (string)x.Element("Genre"),
year = (int)x.Element("Year"),
productID = (string)x.Element("ProductID")
}).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());
}
}
}

Deserialize XML containing a Dictionary

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();
}
}
}

Categories

Resources