how do you retrieve xml data from nested nodes - c#

<CustomerOrders>
<Customers>
<CustomerID>ALFKI</CustomerID>
<Orders>
<OrderID>10643</OrderID>
<CustomerID>ALFKI</CustomerID>
<OrderDate>1997-08-25</OrderDate>
</Orders>
<Orders>
<OrderID>10692</OrderID>
<CustomerID>ALFKI</CustomerID>
<OrderDate>1997-10-03</OrderDate>
</Orders>
<CompanyName>Alfreds Futterkiste</CompanyName>
</Customers>
<Customers>
<CustomerID>ANATR</CustomerID>
<Orders>
<OrderID>10308</OrderID>
<CustomerID>ANATR</CustomerID>
<OrderDate>1996-09-18</OrderDate>
</Orders>
<CompanyName>Ana Trujillo Emparedados y helados</CompanyName>
</Customers>
</CustomerOrders>
How do you retrieve OrderID,CustomerID and OrderDate? i have been trying it for hours already. Can someone help me? Thanks!
XmlNodeList xmlnode = doc.GetElementsByTagName("Customers");
HtmlGenericControl div = new HtmlGenericControl("div");
for(int i = 0; i < xmlnode.Count; i++)
{
Label lbl2 = new Label();
lbl2.Text = xmlnode[i].ChildNodes[1].Name;
div.Controls.Add(lbl2);
RadioButtonList rb1 = new RadioButtonList();
rb1.Items.Add(xmlnode[i].ChildNodes[1].InnerText+"<br>");
div.Controls.Add(rb1);
}
div1.Controls.Add(div);

You can use the XDocument class and its decendants. You can use XPath expressions to delve deeper into the code:
e.g.
using System.Xml.Linq
using System.Xml.XPath
....
XDocument doc= XDocument.Load("sample.xml");
XElement root= doc.Element("CustomerOrders");
var result= root.XPathSelectElements("Customers/CustomerId");
foreach(var customerid in result)
{
.....
}
Depending on what you want to achieve this should put you at the right track. While I was typing the answer, another answer proposes to use XmlDocument class. That should work as well, but when using XDocument you can use Linq, which adds a lot of flexibilty.

XmlDocument doc = new XmlDocument();
doc.LoadXml("yourxmldata");
XmlNodeList customers = doc.DocumentElement.SelectNodes("Customers");
foreach (XmlNode customer in customers)
{
XmlNodeList customerOrders = customer.SelectNodes("Orders");
string customername = customer["CustomerID"].InnerText;
foreach (XmlNode customerOrder in customerOrders)
{
string orderid = customerOrder["OrderID"].InnerText;
string orderdate = customerOrder["OrderDate"].InnerText;
}
}

Here is everything using Xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication47
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("Customers").Select(x => new
{
customerID = (string)x.Element("CustomerID"),
companyName = (string)x.Element("CompanyName"),
orders = x.Elements("Orders").Select(y => new {
orderID = (int)y.Element("OrderID"),
customerID = (string)y.Element("CustomerID"),
date = (DateTime)y.Element("OrderDate")
}).ToList()
}).ToList();
}
}
}

Related

Replace the value by relying on the existing value in XML file

This is a sample XML file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Automation Test</string>
<string name="current_data_state_incoming_call">Incoming Call</string>
<string name="current_data_state_outgoing_call">Outgoing Call</string>
<string name="current_data_state_missed_call">Missed Call</string>
<string name="current_data_state_photo">Photo</string>
<string name="current_data_state_video">Video</string>
<string name="current_data_state_mp3">MP3</string>
<string name="current_data_state_voice_memo">Voice Memo</string>
<string name="current_data_state_phone_book">Phone Book</string>
<string name="current_data_state_phone_booksim">Phone Book(SIM)</string>
<string name="current_data_state_etc">Etc</string>
<string name="current_data_state_schedule">S Planner</string>
</resources>
I have a large file XML file and I want to replace the values in elements depending on their original value.
For example, I want to replace "Outgoing Call" with another word.
I tried this code:
XmlDocument xdoc = new XmlDocument();
xdoc.Load("strings.xml");
XmlElement root = xdoc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("string");
for (int i = 0; i < elemList.Count; i++)
{
xdoc.Save("strings.xml");
if (elemList[i].InnerText == "Incoming Call")
{
// xdoc.LoadXml(File.ReadAllText("strings.xml").Replace(elemList[i].InnerText, "صندوق"));
// MessageBox.Show(elemList[i].InnerText);
elemList[i].SelectSingleNode("resources/string").InnerText="مكالمات قادمة";
xdoc.Save("strings.xml");
}
}
and this code
XmlDocument xdoc = new XmlDocument();
xdoc.Load("strings.xml");
XmlNodeList aNodes = xdoc.SelectNodes("resources/string");
foreach (XmlNode node in aNodes)
{
XmlNode child1 = node.SelectSingleNode("string");
if(child1.InnerText == "Incoming Call")
{
child1.InnerText = "اتصالات قادمة";
}
}
xdoc.Save("strings.xml");
I can not replace the value.
===================================
thanx i solve my prob
var root2 = new XmlDocument();
root2.Load("strings.xml");
var root = new XmlDocument();
root.Load("strings2.xml");
foreach (XmlNode e1 in root2.GetElementsByTagName("string"))
{
string a = e1.Attributes["name"].Value;
foreach (XmlNode ee in root.GetElementsByTagName("string"))
{
string b = ee.Attributes["name"].Value;
if (a == b)
{
e1.FirstChild.Value = ee.FirstChild.Value;
}
}
}
root.Save("strings.xml");
I would use LINQ to XML for this. It makes all kinds of things much simpler than XmlDocument. Here's a complete example to perform a replacement (loading input.xml and writing output.xml):
using System;
using System.Linq;
using System.Xml.Linq;
class Test
{
static void Main()
{
XDocument doc = XDocument.Load("input.xml");
ReplaceValue(doc, "Outgoing Call", "Other value");
doc.Save("output.xml");
}
static void ReplaceValue(XDocument doc, string original, string replacement)
{
foreach (var element in doc.Descendants("string").Where(x => x.Value == original))
{
element.Value = replacement;
}
}
}
You could easily change the method to throw an exception if it didn't find the value you were trying to replace, or if it found more than one element.
An alternative to replacing by value would be to replace by the name attribute, which would be a trivial change:
static void ReplaceNamedValue(XDocument doc, string name, string replacement)
{
foreach (var element in doc.Descendants("string")
.Where(x => (string) x.Attribute("name") == name))
{
element.Value = replacement;
}
}
You'd then call it like this:
ReplaceNamedValue(doc, "current_data_state_outgoing_call", "Other value");
You may want to create file on xml on the fly instead of replace. I prefer using the newer Net library xml linq (XDocument) rather than the older version XmlDocument. Here is an example of the code I would use :
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)
{
string ident = "<?xml version=\"1.0\" encoding=\"utf-8\"?><resources></resources>";
XDocument doc = XDocument.Parse(ident);
XElement resources = doc.Root;
resources.Add(new XElement("string", new object[] {
new XAttribute("name","app_name"),
"Automation Test"
}));
resources.Add(new XElement("string", new object[] {
new XAttribute("name","current_data_state_incoming_call"),
"مكالمات قادمة"
}));
}
}
}
Here is code for replacement
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);
XElement resource = doc.Root;
Dictionary<string, XElement> dict = resource.Elements()
.GroupBy(x => (string)x.Attribute("name"), y => y)
.ToDictionary(x => x.Key, y => y.FirstOrDefault());
if(dict.ContainsKey("app_name"))
{
dict["app_name"].SetValue("Automation Test");
}
if (dict.ContainsKey("current_data_state_incoming_call"))
{
dict["current_data_state_incoming_call"].SetValue("مكالمات قادمة");
}
}
}
}

Retrieving Xml Attribute Value in C#

I'm new to C# & I'm trying to read XML attribute from XML file in my Asp.net web project, when i retrieve attribute content i get this result :
"System.XML.Attribute;"
here is XML file:
<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<!--creating XML file-->
<Document PagesInDocument="1" Filename="YahyaXML">
<Page Filename="YahyaXML" ZonesInPage="1" PageID="0">
<Zone TextLinesInZone="2" zoneLRY="558" zoneLRX="1202"
zoneULY="3" zoneULX="886" ZoneID="0">
<TextLine Content="aaaaaaaaaaa" TextLineID="0"/>
<TextLine Content="aaaaaaaaaaaaaaaaaa" TextLineID="1"/>
</Zone>
</Page>
</Document>
Here is my c# code:
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\Program Files (x86)\NovoDynamics\NovoVerus\api\examples\C#Samples\WebAppTest\Uploads\test-ht.xml");
StringBuilder Content_Value = new StringBuilder();
XmlNodeList aNodes = doc.SelectNodes("/Document/Page/Zone");
XmlNodeList bNodes = doc.SelectNodes("/Document/Page/Zone/TextLine");
foreach (XmlNode aNode in aNodes)
{
XmlAttribute ULX_xml = aNode.Attributes["zoneULX"];
XmlAttribute ULY_xml = aNode.Attributes["zoneULY"];
XmlAttribute LRX_xml = aNode.Attributes["zoneLRX"];
XmlAttribute LRY_xml = aNode.Attributes["zoneLRY"];
if (ULX_xml.Value == TextBox5.Text && ULY_xml.Value == TextBox6.Text && LRX_xml.Value == TextBox7.Text && LRY_xml.Value == TextBox8.Text )
{
foreach (XmlNode bNode in bNodes)
{
//XmlAttribute ContentAttribute = bNode.Attributes["Content"];
if (bNode.Attributes["Content"].Value != null)
{
Content_Value.Append(bNode.Attributes["Content"].Value.ToString());
}
}
Content_Value.Append("\n");
}
}
TextBox9.Text = Content_Value.ToString();
Your code works. Try change first string in your xml file to:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
More: https://msdn.microsoft.com/en-us/library/ms256048(v=vs.120).aspx
Using xml Linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(FILENAME);
reader.ReadLine(); //skip identification
XDocument doc = XDocument.Load(reader);
var results = doc.Descendants("Page").Select(x => new
{
filename = (string)x.Attribute("Filename"),
page = (int)x.Attribute("ZonesInPage"),
id = (int)x.Attribute("PageID"),
zones = x.Elements("Zone").Select(y => new {
textLines = (int)y.Attribute("TextLinesInZone"),
ulx = (int)y.Attribute("zoneULX"),
uly = (int)y.Attribute("zoneULY"),
lrx = (int)y.Attribute("zoneLRX"),
lry = (int)y.Attribute("zoneLRY"),
textLine = y.Elements("TextLine").Select(z => new {
content = (string)z.Attribute("Content"),
id = (int)z.Attribute("TextLineID")
}).ToList()
}).ToList()
}).ToList();
}
}
}

How to get all attribute names from selected XML node in C#

This is my XML file. I need to select one test element and get all attributes name from its result child nodes.
<?xml version="1.0" encoding="UTF-8"?>
<summary>
<test>
<id>test 1</id>
<result value="-45">330</result>
<result value="0">300</result>
<result value="45">340</result>
</test>
<test>
<id>test 3</id>
<result value="-45">330</result>
<result value="0">300</result>
<result value="45">340</result>
</test>
</summary>
I wrote below code. but repeat same values and I want to stop it.
XmlDocument xd = new XmlDocument();
xd.Load(_xmlFilePath);
XmlNodeList nodelist = xd.GetElementsByTagName("result");
foreach (XmlNode node in nodelist)
{
string attrVal = node.Attributes["value"].Value;
Console.WriteLine(attrVal);
}
Any suggestion is appreciated.
Thanks.
You can use LINQ to Xml with XDocument class
var doc = XDocument.Load(_xmlFilePath);
var distinctResults = doc.Descendants("result")
.Select(element => element.Attribute("value").Value)
.Distinct();
foreach(var result in distinctResults)
{
Console.WriteLine(result);
}
Or with using of HashSet<string>
var results = doc.Descendants("result")
.Select(element => element.Attribute("value").Value);
var distinctResults = new HashSet<string>(results);
foreach(var result in distinctResults)
{
Console.WriteLine(result);
}
Try following :
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);
string id = "test 1";
var results = doc.Descendants("test").Where(x => (string)x.Element("id") == id).FirstOrDefault().Elements("result").Select(x => new
{
angle = (int)x.Attribute("value"),
length = (int)x
}).ToList();
}
}
}

Counting and get sum value of child node values from XML with LINQ

This is my XML file and I'm using C# and LINQ:
<?xml version="1.0" encoding="utf-8"?>
<Votes>
<person id="1">
<votes>9</votes>
<votes>1</votes>
</person>
<person id="2">
<votes>5</votes>
<votes>6</votes>
</person>
<person id="3">
<votes>5</votes>
<votes>5</votes>
<votes>2</votes>
<votes>5</votes>
</person>
</Votes>
I want to get the number of votes for each personID, groupped by id, like:
personID = 1, count = 2
personID = 2, count = 2
personID = 3, count = 4
I also want to get the sum value of these votes, like:
personID = 1, sum = 10
personID = 2, sum = 11
personID = 3, sum = 17
Use xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\Test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
var results = doc.Descendants("person").Select(x => new {
id = x.Attribute("id"),
count = x.Elements("votes").Count(),
sum = x.Elements("votes").Select(y => (int)y).Sum()
}).ToList();
}
}
}
You can use linq to Xml for this
//Your Xml string goes into _xml
var doc = XDocument.Parse(_xml);
var baseGrouping = doc.Descendants("Votes")
.SelectMany(a=>a.Descendants()
.Select(b=>new{ personId = a.Attribute("id").Value, vote = int.Parse(b.Value) }));
var aggregates = baseGrouping.GroupBy(a=>a.personId)
.Select(a=>new {
personId=a.Key,
count = a.Count(),
sum = a.Sum()
});
You can use a [XmlDocument][1] to parse the XML, [XPath][1] to select the nodes to process and Linq to sum up the votes. Alternatively you could use LINQ to XML.
https://dotnetfiddle.net/6HlU3s
XmlDocument doc = new XmlDocument();
doc.LoadXml("Your XML");
foreach (XmlNode person in doc.SelectNodes("//person"))
{
int id = int.Parse(person.Attributes["id"].Value);
List<int> votes = new List<int>();
foreach (XmlNode node in person.SelectNodes("./votes"))
{
votes.Add(int.Parse(node.InnerText));
}
int voteCount = votes.Count;
int voteSum = votes.Sum();
Debug.WriteLine("Person {0}: {1} votes (sum {2})", id, voteCount, voteSum);
}

XML to String List

I have some code that I need to put into a string list in C# and I am reading this code from an XML files and the layout of it is something like below...
<?xml version="1.0"?>
<accountlist>
<main>
<account id="1" special_id="4923959">
<username>Adam</username>
<motto>Hello Everyone>
<money>1004</money>
<friends>394</friends>
<rareid>9</rareid>
<mission>10</mission>
</account>
</main>
</accountlist>
How can I put each account tag into a string list? from the first < account > to the < / account > tag?
Please do NOT tell me to go to the link below as it does NOT work!!
How to read a XML file and write into List<>?
So far I have tried the below code, and the string list just stays empty
XDocument doc = XDocument.Parse(this._accountsFile);
List<string> list = doc.Root.Elements("account")
.Select(element => element.Value)
.ToList();
this._accounts = list;
You'll have to use Descendants instead of Elements:
List<string> list = doc.Root.Descendants("account").Descendants()
.Select(element => element.Value)
.ToList();
Elements only returns child elements of the element (in case of the root element this means <main>).
Descendants returns the entire tree inside the element.
Also: You'll have to fix the tag <motto>Hello Everyone> to <motto>Hello Everyone</motto>
This will work on your example (but you need to close this tag <motto>Hello Everyone>
public List<string> GetAccountsAsXmlList(string filePath)
{
XmlDocument x = new XmlDocument();
x.Load(filePath);
List<string> result = new List<string>();
XmlNode currentNode;
foreach (var accountNode in x.LastChild.FirstChild.ChildNodes)
{
currentNode = accountNode as XmlNode;
result.Add(currentNode.InnerXml);
}
return result;
}
EDIT as an answer to your question:
Is there a way I can get the id and specal_id in a seperate string?
you can use currentNode.Attributes["YourAttributeName"].Value, to get the values.
assume you have class Account :
class Account
{
public string accountXml { get; set; }
public string Id { get; set; }
public string Special_id { get; set; }
}
Then :
public List<Account> GetAccountsAsXmlList(string filePath)
{
XmlDocument x = new XmlDocument();
x.Load(filePath);
List<Account> result = new List<Account>();
XmlNode currentNode;
foreach (var accountNode in x.LastChild.FirstChild.ChildNodes)
{
currentNode = accountNode as XmlNode;
result.Add(new Account
{
accountXml = currentNode.InnerXml,
Id = currentNode.Attributes["id"].Value,
Special_id = currentNode.Attributes["special_id"].Value,
});
}
return result;
}
Use XPath to get the account element first:
using System.Xml.XPath;
XDocument doc = XDocument.Parse(xml);
foreach(var account in doc.XPathSelectElements("accountlist/main/account")){
List<string> list = account.Descendants()
.Select(element => element.Value)
.ToList();
}
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication37
{
class Program
{
static void Main(string[] args)
{
string input =
"<?xml version=\"1.0\"?>" +
"<accountlist>" +
"<main>" +
"<account id=\"1\" special_id=\"4923959\">" +
"<username>Adam</username>" +
"<motto>" +
"Hello Everyone>" +
"<money>1004</money>" +
"<friends>394</friends>" +
"<rareid>9</rareid>" +
"<mission>10</mission>" +
"</motto>" +
"</account>" +
"</main>" +
"</accountlist>";
XDocument doc = XDocument.Parse(input);
var results = doc.Descendants("accountlist").Select(x => new {
id = x.Element("main").Element("account").Attribute("id").Value,
special_id = x.Element("main").Element("account").Attribute("special_id").Value,
username = x.Element("main").Element("account").Element("username").Value,
motto = x.Element("main").Element("account").Element("motto").FirstNode.ToString(),
money = x.Element("main").Element("account").Element("motto").Element("money").Value,
friends = x.Element("main").Element("account").Element("motto").Element("friends").Value,
rareid = x.Element("main").Element("account").Element("motto").Element("rareid").Value,
mission = x.Element("main").Element("account").Element("motto").Element("mission").Value,
}).ToList();
}
}
}

Categories

Resources