Parsing XML element to get value of an element - c#

I have the following XML
<?xml version="1.0" encoding="UTF-8"?> <i18nText><Country code="DE" language="de" text="nach Datum" /><Country code="US" language="en" text="by Date" /></i18nText>
I'm trying to get the value of the text element.There can be different values based on the language element.
How can i populate it into a dictionary ie: value of text for each language .

XmlDocument doc = new XmlDocument();
doc.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?> <i18nText><Country code=\"DE\" language=\"de\" text=\"nach Datum\" /><Country code=\"US\" language=\"en\" text=\"by Date\" /></i18nText>");
XmlNodeList countries = xDoc.GetElementsByTagName("Country");
Dictionary<string, string> dict = new Dictionary<string, string>();
for (int i = 0; i < countries.Count; i++)
{
dict.Add(countries[i].Attributes["language"]?.InnerText, countries[i].Attributes["text"]?.InnerText);
}

var languageToText = XDocument
.Parse(content)
.Descendants("Country")
.Select(p => new
{
language = p.Attribute("language"),
text = p.Attribute("text")
})
.ToDictionary(
p => p.language,
p => p.text);

I would use Linq to Xml, it's more declarative and easier to read than using loops.
using System.Linq;
using System.Xml.Linq;
var xml = #"<?xml version=""1.0"" encoding=""UTF - 8""?> <i18nText><Country code=""DE"" language=""de"" text=""nach Datum"" /><Country code=""DE"" language=""de"" text=""nach Datum"" /><Country code=""US"" language=""en"" text=""by Date"" /></i18nText>";
var doc = XDocument.Parse(xml);
var dic = (from country in doc.Root.Elements()
select new { language=country.Attribute("language").Value, text=country.Attribute("text").Value }).
Distinct().
ToDictionary(country => country.language, country => country.text);

Related

How To Store a XML section by the tag

I would like to store the original section of a XML string, split by the base on each root element of <ROW NUMBER="1">, and assign to a string.
May I know how can it be done?
<?xml version="1.0"?>
<ROWS>
<ROW NUMBER="1">
<PersonID>P1</PersonID>
<PersonName>JAMES</PersonName>
</ROW>
<ROW NUMBER="2">
<PersonID>P2</PersonID>
<PersonName>MARY</PersonName>
</ROW>
</ROWS>
Expected result:
string person1 = "<PersonID>P1</PersonID><PersonName>JAMES</PersonName>"
string person2 = "<PersonID>P2</PersonID><PersonName>MARY</PersonName>"
Thank you.
I usually use a dictionary like this :
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, List<XElement>> dict = doc.Descendants("ROW")
.GroupBy(x => (string)x.Element("PersonID"), y => y)
.ToDictionary(x => x.Key, y => y.Descendants().ToList());
}
}
}
This is relatively trivial:
var xml = "<?xml version=\"1.0\"?><ROWS> <ROW NUMBER=\"1\"> <PersonID>P1</PersonID> <PersonName>JAMES</PersonName> </ROW> <ROW NUMBER=\"2\"> <PersonID>P2</PersonID> <PersonName>MARY</PersonName> </ROW></ROWS>";
// Load XML into XmlDocument
var doc = new XmlDocument();
doc.LoadXml(xml);
// Select the ROW nodes
var nodes = doc.SelectNodes("/ROWS/ROW");
// Select the value of the NUMBER attribue and the InnerXML into an anonymous object
// and convert into a dictionary with the key personX (where X is the value of the NUMBER attribute)
var dictionary = nodes
.Cast<XmlNode>()
.Select(n => new { Row = n.Attributes["NUMBER"].Value, Xml = n.InnerXml })
.ToDictionary(r => $"person{r.Row}", r => r.Xml);
Disclaimer: the ToDictionary part will fail if a duplicate NUMBER attribute value exists (DuplicateKeyException). You might need to write some code to handle it.

Looping through xmlnodes using Xdocument

I have an xml string like this
<Test>
<ConnectionParameters>
<ConnectionParameter DisplayName="asd" Id="cgfh" IsPassword="false" IsRequired="true"> </ConnectionParameter>
<ConnectionParameter DisplayName="asdasd" Id="fgh" IsPassword="false" IsRequired="true"></ConnectionParameter>
<ConnectionParameter DisplayName="asdasd" Id="hdfh" IsPassword="false" IsRequired="true"></ConnectionParameter>
<ConnectionParameter DisplayName="asdad" Id="dfgdf" IsPassword="false" IsRequired="true"> </ConnectionParameter>
</ConnectionParameters>
</Test>
How can I loop through each "ConnectionParameter" tag inorder to get the attributes like Id,DisplayName etc using xdocument?
I tried like this,
XDocument xdoc = new XDocument();
xdoc= XDocument.Parse(fileContent);
var saveResult = from b in xdoc.Descendants("ConnectionParameters")
select new
{
success = (string)b.Element("ConnectionParameter").Attribute("Id").Value ?? string.Empty,
};
But it only returns the first node only
You're currently looping through all the ConnectionParameters elements (of which there's only one) and selecting the first ConnectionParameter element (using the Element call). You want to just loop through the ConnectionParameter elements:
// Note the lack of creating a new XDocument for no reason
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = from b in xdoc.Descendants("ConnectionParameter")
select new
{
success = (string) b.Attribute("Id") ?? ""
};
Or to avoid creating an anonymous type for no obvious reason, and using plain "dot notation" as the query expression isn't helping you much:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
If you prefer to make the parent element names explicit, you could use:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Element("Test")
.Element("ConnectionParameters")
.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
Or:
XDocument xdoc = XDocument.Parse(fileContent);
var saveResult = xdoc.Root
.Element("ConnectionParameters")
.Descendants("ConnectionParameter")
.Select(b => (string) b.Attribute("Id") ?? "");
Load your xml into xDocument, then you can do something like this (can't remember exact syntax)
xDoc.Root.Descendants("ConnectionParameters").Attribute("DisplayName").Value;

Get node property of XmlDocument in C#

I'm using this xml structure:
<park>
<car title="Ferrari" available="true">
<url>http://www.ferrari.com/</url>
</rss>
</park>
And this is my code in C#:
XmlDocument doc = new XmlDocument();
doc.Load("Settings.xml");
XmlNodeList list = doc.SelectNodes("/park/car");
foreach (XmlNode item in list)
{
string x = item["#title"].InnerText;
}
I just want to get "title" property but i can't get it working. I'm using "#" but without success.
Try this code:
string x = item.Attributes["title"].Value;
I suggest you to use LINQ to XML for parsing xml:
var xdoc = XDocument.Load("Settings.xml");
var titles = xdoc.XPathSelectElements("//park/car")
.Select(c => (string)c.Attribute("title"));
Or without XPath:
var titles = xdoc.Descendants("park")
.Elements("car")
.Select(c => (string)c.Attribute("title"));

Parse generic XML string using C#

suppose I have the following XML string:
<?xml version="1.0" encoding="utf-8" ?>
<items>
<item1>value1</item1>
<item2>value2</item2>
<item3>value3</item3>
<item4>value4</item4>
<item5>value5</item5>
<item6>value6</item6>
</items>
I need to parse it in a generic way as it may be updated later, and I don't need to modify my code accordingly.
So I have tried the following:
public static Dictionary<string, string> Parser(string xmlString)
{
Dictionary<string, string> parserDictionary = new Dictionary<string, string>();
using (StringReader stringReader = new StringReader(xmlString))
using (XmlTextReader reader = new XmlTextReader(stringReader))
{
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
parserDictionary.Add(reader.Name, reader.ReadString());
break;
}
}
}
return parserDictionary;
}
This code have 2 issues:
It parse the <items> element with null value, I don't need to
parse it
it ignores <item1>
please advise
Why not something like this:
var parserDictionary = XDocument.Create(xmlString)
.Descendants("items")
.Elements()
.Select(elem => new { Name = elem.Name.LocalName, Value = elem.Value })
.ToDictionary(k => k.Name, v => v.Value);
You could probably even do this:
var parserDictionary = XDocument.Create(xmlString)
.Descendants("items")
.Elements()
.ToDictionary(k => k.Name.LocalName, v => v.Value);
If you need to convert XML to an object representation than that's trivially easy
XDocument xDoc = XDocument.Parse(xmlString);
That's really all you need to do. Once you do that, you can query your xDoc with the Elements, Element, Attribute, Attributes and Descendants Properties.
For an example, here's some code that will print all of your values
XDocument xDoc = XDocument.Parse(xmlString);
foreach(XElement e in xDoc.Elements())
{
Console.WriteLine(e.Value);
}

Getting value of an attribute within namespace

I am trying to process the following XML:
<rif:Rif xmlns:rif="rif" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" rif:numeroRif="XYZXYZXYZ">
<rif:Nombre>Nombre</rif:Nombre>
<rif:AgenteRetencionIVA>SI</rif:AgenteRetencionIVA>
<rif:ContribuyenteIVA>SI</rif:ContribuyenteIVA>
<rif:Tasa />
</rif:Rif>
An I am using the next code:
XDocument doc = XDocument.Parse(result);
var q = from item in doc.Descendants()
let attributeType = item.Attribute("AgenteRetencionIVA").Value
select item;
I have problems to get the attribute rif:AgenteRetencionIVA. How do I to do it?
Looks like tou need to specify custom namespace:
string xml = #"...";
XName nameRif = "rif";
XDocument doc = XDocument.Parse(xml);
var q = from item in doc.Descendants()
let attributeType = item.Attribute(nameRif + "AgenteRetencionIVA")
select item.Value;
var a = q.ToArray();

Categories

Resources