I have this xml:
<?xml version="1.0" encoding="utf-8"?>
<Packet>
<Header>
<Id>1234-1234-1234</Id>
</Header>
<Customers>
<Customer>
<Name>Try</Name>
<Age>20</Age>
</Customer>
</Customers>
</Packet>
And this is how I convert it to object:
XDocument xdoc = XDocument.Load(xml);
List<Customer> customers = (from customer in xdoc.Element("Customers").Element("Customer")
select new Customer
{
Name = customer.Element("Name").Value,
Age = customer.Element("Age").Value
}).ToList();
My problem is when I tried to run this code, I got an exception error saying that object reference not set to an instance.
But when i changed my xml to this:
<?xml version="1.0" encoding="utf-8"?>
<Customers>
<Customer>
<Name>Try</Name>
<Age>20</Age>
</Customer>
</Customers>
It started working and I am getting the name and age. However, the packet and header is one of the requirements on my xml files. How am I gonna do that?
EDIT:
Thanks for all the solutions! They are all working, but may I know what is the best to use (best practices, etc) Thanks!
You can use Descendants() method to find elements in xml tree.
List<Customer> customers = (from customer in xdoc.Descendants("Customer")
select new Customer
{
Name = customer.Element("Name").Value,
Age = customer.Element("Age").Value
}).ToList();
Change your query source to:
xdoc.Root.Element("Customers").Elements("Customer")
Element method looks for the element on current level, which is the root for XDocument. That's why the query didn't work.
Try changing your LINQ query to:
XDocument xdoc = XDocument.Load(xml);
List<Customer> customers = (from customer in xdoc.Element("Packet").Element("Customers").Element("Customer")
select new Customer
{
Name = customer.Element("Name").Value,
Age = customer.Element("Age").Value
}).ToList();
Because your Customers element is located inside your Packet element.
Related
**I have an XML like this-
<?xml version="1.0" encoding="UTF-8"?>
<Tool_Parent>
<tool name="ABCD" id="226">
<category>Centralized</category>
<extension_id>0</extension_id>
<uses_ids>16824943 16824944</uses_ids>
</tool>
<tool name="EFGH" id="228">
<category>Automated</category>
<extension_id>0</extension_id>
<uses_ids>92440 16824</uses_ids>
</tool>
</Tool_Parent>
Based on the id of tool i want to print the uses_ids value,i.e if i search for 228 i should get 92440 16824.
I had tried like-
var toolData = (from toolElement in doc.Descendants("tool")
select new Tool_poco
{
a_Name = tool.Attribute("name").Value,
a_Id = tool.Attribute("id").Value,
e_ExtensionId = tool.Element("extension_id").Value,
e_UsesIds =tool.Element("uses_parm_ids").Value
});
where Tool_poco is a poco class for tool node containing declaration for member variable.
Now I want to get information related to a particular tool id in toolData variable.How to do it?
Note: I have variable like-
searched_Tool_id = Tool_Id_txtBx.Text.ToString();
Please let me know a way through which i can modify my above query for toolData.**
You can modify your query as
Tool_poco toolData = (from el in xelement.Elements("Employee")
where (string)el.Attribute("id") == "226"
select new Tool_poco
{
a_Name = el.Attribute("name").Value,
a_Id = el.Attribute("id").Value,
e_ExtensionId = el.Element("Name").Value,
e_UsesIds = el.Element("uses_ids").Value
}).FirstOrDefault();
You could start by doing something like this once you have an XDocument object loaded and ready:
var xdoc = XDocument.Parse(
#"<?xml version=""1.0"" encoding=""utf-8""?>
<Tool_Parent>
<tool name=""ABCD"" id=""226"">
<category>Centralized</category>
<extension_id>0</extension_id>
<uses_ids>16824943 16824944</uses_ids>
</tool>
<tool name=""EFGH"" id=""228"">
<category>Automated</category>
<extension_id>0</extension_id>
<uses_ids>92440 16824</uses_ids>
</tool>
</Tool_Parent>");
var root = xdoc.Root; // Got to have that root
if (root != null)
{
var id228query = (from toolElement in root.Elements("tool")
where toolElement.HasAttributes
where toolElement.Attribute("id").Value.Equals("228")
let xElement = toolElement.Element("uses_ids")
where xElement != null
select xElement.Value).FirstOrDefault();
Console.WriteLine(id228query);
Console.Read();
}
Output: 92440 16824
**Note: In reference to your example, one possible reason it was not working
for you could be that your xml references an element with name "uses_ids",
however, your query references an element with a similar, but not exact,
spelling with name "uses_parm_ids".**
Friends,
My school project is having an xml data file:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>Somewhere</add>
<mobile>0000</mobile>
.
.
.
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
My Windowsform "EditPatients_Load" is able to fetch all info of patient Jhon, and now let's assume that the Admin needs to change some information in the form & resubmit.
Then how to write back all values to Jhon's account in the same xml
file????
I'm not able to makeup the logical code, even if I check the node if (patients.paptient.name = "nameComboBox.text").... how to make sure that I'm writing other values on proper place?
Rgrdz,
Try this:
//string xml =
//#"<patients><patient><regNo>2012/Mar/003</regNo><name>Jhon</name><add>Somewhere
//</add><mobile>0000</mobile><stay>2</stay><costofroom>100</costofroom><total>200</total>
//</patient></patients>";
XDocument xmlDoc = XDocument.Load(#"c:\abc.xml");
var items = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item);
if (items.Count() > 0)
{
var item = items.First();
item.SetElementValue("add", "New New Address");
xmlDoc.Save(#"c:\abc.xml", SaveOptions.None);
}
You can get single element using
var item = (from item in xmlDoc.Descendants("patient")
where item.Element("name").Value == "Jhon"
select item).FirstOrDefault();
then update it using SetElementValue() method.
//Updated Xml
<?xml version="1.0" encoding="utf-8"?>
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>New Address</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Reference:
Update XML with C# using Linq
I would take the xml serialization/deserialization route to solve this:
http://support.microsoft.com/kb/815813
How to Deserialize XML document
That way you can work with objects and not have to parse xml files manually.
If you're using .NET 3.5 onward you can use the XDocument class like the following. I'm assuming your content is in a .xml file.
XDocument xdoc = XDocument.Load(#"C:\Tmp\test.xml");
//this would ensure you get the right node and set its text content/value
xdoc.Element("patients")
.Element("patient").Element("add").Value = "some new address?";
xdoc.Save(#"C:\Tmp\test.xml");
The file test.xml would change to:
<patients>
<patient>
<regNo>2012/Mar/003</regNo>
<name>Jhon</name>
<add>some new address?</add>
<mobile>0000</mobile>
<stay>2</stay>
<costofroom>100</costofroom>
<total>200</total>
</patient>
</patients>
Given the following XML, what query can I use to extract the value of preapprovalKey to a string variable? Still a little new to LINQ to XML.
<?xml version="1.0" encoding="UTF-8" ?>
- <ns2:PreapprovalResponse xmlns:ns2="http://svcs.paypal.com/types/ap">
- <responseEnvelope>
<timestamp>2011-04-05T18:35:32.952-07:00</timestamp>
<ack>Success</ack>
<correlationId>7cec030fa3eb2</correlationId>
<build>1655692</build>
</responseEnvelope>
<preapprovalKey>PA-9AG427954Y7578617</preapprovalKey>
</ns2:PreapprovalResponse>
XDocument doc = XDocument.Load("test.xml");
string preapprovalKey = doc.Descendants("preapprovalKey").Single().Value;
See below my exmaple, it help you to resolve your issue and problem. :)
Consider this below XML is there as one of the SQL table's column.
<Root>
<Name>Dinesh</Name>
<Id>2</Id>
</Root>
The objective of the query is to fetch the Name from the XML. In this example we will fetch the 'Dinesh' as the value.
var Query = (from t in dbContext.Employee.AsEnumerable()
where t.active == true
select new Employee
{
Id = t.AtpEventId,
Name = XDocument.Parse(t.Content).Descendants("Root").Descendants("Name").ToList().
Select(node => node.Value.ToString()).FirstOrDefault()
});
Note the following :-
Here in above LINQ , t.active == true is just an example to make some condition if needed.
Please note, in the above LInQ query, always use the AsEnumerable(), as I did in the
first file of the Linq query.exmaple(var Query = (from t in dbContext.Employee.AsEnumerable())
Descendants("Root").Descendants("Name") , Here Root should be the Element matching with the XML, And under the Root we have Name element, thats why we wrote
Descendants("Root").Descendants("Name")
For any further clarification you can reach me via danish.eggericx#gmail.com
I'm trying to get all the email nodes for the customers in the sample xml and binding it to a grid. I can't seemt to get past the linq query!
Sample XML:
<group>
<customer>
<email>testing#testing.com></email>
</customer>
<customer>
<email>testing2#testing.com</email>
</customer>
</group>
var query = from result in xml.Elements("customer")
select new
{
email = xml.Element("email").Value
};
gridview1.DataSource = query;
gridview1.DataBind();
Elements() will only get you direct children, therefore, if your xml variable is an XDocument, its only direct children (according to the little sample) are group elements.
Try:
var query = from result in xml.Descendants("customer")
select new { email = result.Element("email").Value };
I have a problem using Linq To Xml.
A simple code. I have this XML:
<?xml version="1.0" encoding="utf-8" ?>
<data xmlns="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/directory file.xsd">
<contact>
<name>aaa</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>sss</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>bbb</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
<contact>
<name>ccc</name>
<email>email#email.ext</email>
<birthdate>2002-09-22</birthdate>
<telephone>000:000000</telephone>
<description>Description for this contact</description>
</contact>
I want to get every contact mapping it on an object Contact. To do this I use this fragment of code:
XDocument XDoc = XDocument.Load(System.Web.HttpRuntime.AppDomainAppPath + this.filesource);
XElement XRoot = XDoc.Root;
//XElement XEl = XElement.Load(this.filesource);
var results = from e in XRoot.Elements("contact")
select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null);
List<Contact> cntcts = new List<Contact>();
foreach (Contact cntct in results) {
cntcts.Add(cntct);
}
Contact[] c = cntcts.ToArray();
// Encapsulating element
Elements<Contact> final = new Elements<Contact>(c);
Ok just don't mind that all: focus on this:
When I get the root node, it is all right, I get it correctly.
When I use the select directive I try to get every node saying: from e in
XRoot.Elements("contact")
OK here's the problem: if I use: from e in XRoot.Elements() I get all contact nodes, but if I use: from e in XRoot.Elements("contact") I GET NOTHING: Empty SET.
OK you tell me: Use the other one: OK I DO SO, let's use:
from e in XRoot.Elements(), I get all nodes anyway, THAT's RIGHT BUT HERE COMES THE OTHER PROBLEM:
When Saying: select new Contact((string)e.Element("name"), (string)e.Element("email"), "1-1-1", null, null); I Try to access <name>, <email>... I HAVE TO USE .Element("name") AND IT DOES NOT WORK TOO!!!!!!!!WHAT THE HELL IS THIS????????????? IT SEEMS THAT I DOES NOT MATCH THE NAME I PASS But how is it possible. I know that Elements() function takes, overloaded, one argument that is an XName which is mapped onto a string. Please consider that the code I wrote come from an example, It should work.
Pretty easy: there's a XML namespace in play, which you're ignoring:
<data xmlns="http://www.example.com"
**************************
You need to add that to your Linq-to-XML queries!
Something like:
XNamespace ns = "http://www.example.com";
and then
XRoot.Elements(ns + "contact")
and of course, also use the XML namespace when accessing the child elements:
var results = from e in XRoot.Elements("contact")
select new Contact(e.Element(ns + "name").Value,
e.Element(ns + "email").Value,
"1-1-1", null, null);
That should help. See the MSDN docs on Working with XML Namespaces for more details.
For me I solved it like that because I didn't had a namespace in my XML:
xmldoc.Root.Elements("contact");
I forgot to use the "Root" method.