LINQ to XML Select Nodes by duplicate child node attributes - c#

Need to pull out the Employees who have a pager.
<Employees>
<Employee>
<Name>Michael</Name>
<Phone Type="Home">423-555-0124</Phone>
<Phone Type="Work">800-555-0545</Phone>
<Phone Type="Mobile">424-555-0546</Phone>
<Phone Type="Cell">424-555-0547</Phone>
<Phone Type="Pager">424-555-0548</Phone>
</Employee>
<Employee>
<Name>Jannet</Name>
<Phone Type="Home">423-555-0091</Phone>
<Phone Type="Work">800-555-0545</Phone>
</Employee>
</Employees>
I've got LINQ to get all the Phone nodes that have a pager and I can get all the employees. I can't wrap my head aroud drilling down to the phone node but still selecting the employee node?
var data = XElement.Load(#"employee.XML" );
var whoHasPager = from teamMember in data.Elements("Employee")
where (string)teamMember.Element("Phone").Attribute("Type") == "Pager"
select teamMember;

How about this:
var whoHasPager = from teamMember in data.Elements("Employee")
where teamMember.Elements("Phone").Any(
p => p.Attribute("Type").Value == "Pager")
select teamMember;

The problem is that .Element will return the first element and not all of them of type Phone.

Try this:
var whoHasPager = from teamMember in data.Elements("Employee")
where teamMember.Elements("Phone").Any(x => x.Attribute("Type").Value == "Pager")
select teamMember;

You should see it as an SQL Statement maybe
SELECT employee from Employees where Phone Type='Pager'
therefore, the from statement should be Employees...
Note: I'm not really good in LINQ, but I think the idea is the same...

You could try using an XPath expression:
var data = XElement.Load(#"employee.XML" );
var whoHasPager =
from teamMember in data.Elements("Employee")
where teamMember.XPathSelectElement("Phone[#Type='Pager']") != null
select teamMember;

var whoHasPager = doc.XPathSelectElements(
"//Employee/Phone[#Type = 'Pager']/.."
);

Related

Linq to XML Querying Data in C#

XML
<?xml version="1.0" encoding="utf-8" ?>
<Employees>
<Employee>
<EmpId>1</EmpId>
<Name>Sam</Name>
<Sex>Male</Sex>
<Salary>40000</Salary>
<Phone Type="Home">423-555-0124</Phone>
<Phone Type="Work">424-555-0545</Phone>
<Address>
<Street>7A Cox Street</Street>
<City>Acampo</City>
<State>CA</State>
<Zip>95220</Zip>
<Country>USA</Country>
</Address>
</Employee>
<Employee>
<EmpId>2</EmpId>
<Name>Lucy</Name>
<Sex>Female</Sex>
<Salary>20000</Salary>
<Phone Type="Home">143-555-0763</Phone>
<Phone Type="Work">434-555-0567</Phone>
<Address>
<Street>Jess Bay</Street>
<City>Alta</City>
<State>CA</State>
<Zip>95701</Zip>
<Country>USA</Country>
</Address>
</Employee>
LINQ expression c#
var Pro = from u in doc.Descendants("Employee") select u;
foreach (var x in Pro)
{
Response.Write(string.Format("EMP ID: {0}, Emp Name: {1}", x.Element("EmpId"), x.Element("Name")));
}
I'm able to query the fields like EmpID, Name, Salary, etc.
But How to query the Address fields like Street, City, State, Zip, Country?
Thanks in advance.
Use
x.Descendants("Address").First().Element("Street")
I would also do what Reniuz suggested and deserialize to an object but here is an example of how you currently do it:
foreach (var x in Pro)
{
Response.Write("EMP ID: {0}, Emp Name: {1}\r\n", x.Element("EmpId"), x.Element("Name"));
var adrs = x.Descendants("Address");
foreach (var a in adrs)
{
Response.Write("\tAddress Street: {0}, City: {1}\r\n", a.Element("Street"), a.Element("City"));
}
}
Take XML into the Variable and Use Like
XDocument doc = XDocument.Parse(XMLVariableString);
var FirstPart = from node in doc.Descendants("items") select node; //Select Data from doc using
List<ListName> valuesNodes = new List<ListName>(); //create any with i.e <==
Create One List with the Same Name as in XML and Created Sub List for Address Containing the all the fields of Address
Use the Same Query you have used but select from FirstPart.
Now you can easily handle data from var FirstPart
The Address elements you are trying to look for can be accessed by first selecting all the Address elements by using x.Elements("Address"). Each nested Address element can then be selected using the .Element() function.
So the parameters for Response.Write() should look something like:
x.Elements("Address").Element("Street");

XML Get element based on attribute

Can someone please help me. I'm new to XML and xElement.
How can I get number of men where year = 2013? The result should be 300.
I have this XML:
<company>
<department>
<departmentname>Dep 1</departmentname>
<year id = "2012">
<men>200</men>
<women>1000</women>
</year>
<year id = "2013">
<men>300</men>
<women>400</women>
</year>
</department>
</company>
I have this code (not working):
XElement company = XElement.Load(Server.MapPath(myXML.xml));
var men = (from a in company.Elements("department").Elements("year")
where (string)a.Attribute("id").Value == "2013"
select (string)(a.Element("men"))).ToList<string>();
What about using XPath?
var xmldoc = XDocument.Parse(#"<?xml version='1.0' encoding='utf-8'?>
<company>
<department>
<departmentname>Dep 1</departmentname>
<year id = '2012'>
<men>200</men>
<women>1000</women>
</year>
<year id = '2013'>
<men>300</men>
<women>400</women>
</year>
</department>
</company>");
Console.WriteLine(
xmldoc.XPathSelectElement(
"/company/department/year[#id='2013']/men").Value);
Assuming you want it from all departments
int mens=company.Descendants("year")
.Where(x=>x.Attribute("id").Value=="2013")
.Sum(x=>int.Parse(x.Element("men").Value));
Your query should be
int men = (from a in company.Elements("department").Elements("year")
where a.Attribute("id").Value == "2013"
select int.Parse(a.Element("men").Value)).Sum();
XElement company = XElement.Load(Server.MapPath(myXML.xml));
var txt = company.Descendants("men")
.First(x => int.Parse(x.Parent.Attribute("id").Value) == 2013).Value;
Not very robust but will do the job in your case and you should get the idea.
And with LINQ syntax rather than extension method:
var txt =
(from c in company.Descendants("men")
where c.Parent.Attribute("id").Value == "2013"
select c).First().Value;
Ok guys. I used this and it's working
Thank you for your help!
XElement com = (from p in company.Elements("department")
where (string)p.Element("departmentname").Value == "Dep 1"
select p).First();
var men= (from a in com.Elements("year")
where (string)a.Attribute("id") == "2013"
select (string)(a.Element("men"))).ToList<string>();

Getting attributes from same-named XDocument elements using LINQ

I've been coding a program that stores employee data using XDocument:
<!-- School Employee Data -->
<SchoolData storeName="mikveIsrael" location="mikve">
<employee id="1">
<personalInfo>
<name>Ilan Berlinbluv</name>
<zip>58505</zip>
</personalInfo>
<employeeInfo>
<salary>5000</salary>
<id>1</id>
</employeeInfo>
</employee>
<employee id="2">...</employee>
</SchoolData>
I want my program to read every employee id attrib, but I don't know how to do so. Instead, I tried doing this:
var ids = from idz in doc.Descendants("SchoolData")
select new
{
id1 = idz.Element("employee").Attribute("id").Value
};
where doc is the XDocument var. It returns just the first one, but I want it to return an array or List<string>, I just don't know how to iterate through all the same-named employee elements.
XDocument doc = XDocument.Parse(xml);
List<string> ids = doc.Descendants("employee")
.Select(e => e.Attribute("id").Value)
.ToList();
This may helps:
var xDoc = XDocument.Load(path);
var result = xDoc.Descendants("employee")
.SelectMany(i => i.Attribute("id").Value)
.ToList();

C# - Access XML attributes

I want to access an attribute type where the value of abc is female
XElement xelement = XElement.Load("..\\..\\Employees.xml");
var name = from nm in xelement.Elements("Employee")
where (string)nm.(Element("Abc") == "Female").Attribute("Type") == "Att"
select nm;
This didn't work. Any way to make it happen?
Something like this would work. It would be useful to see the Xml though.
var doc = XDocument.Load("c:\\temp\\test.xml");
var result = doc.Descendants("Employee")
.Where(x=>(string)x.Value== "female")
.Select(x=>x.Attribute("type").Value);
This is assuming the xml is something like this, the query would return "foo1".
<?xml version="1.0"?>
<root>-
<Employee type="foo">
<abc>male</abc>
</Employee>
<Employee type="foo1">
<abc>female</abc>
</Employee>
<Employee type="foo2">
<abc>male</abc>
</Employee>
</root>
Your code doesn't make any sense.
You cannot nest comparisons and casts and objects like that.
Instead, you need to use the && operator to check each condition separately.
Use XMLReader
More information from MSDN:http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.aspx

C# Linq to XML query

<World>
<Animals>
<Tab>
<Dogs id ="1">
<Dog1></Dog1>
<Dog2></Dog2>
<Dog3></Dog3>
</Dogs>
<Dogs id ="2"></Dogs>
<Dogs id ="3"></Dogs>
</Tab>
</Animals>
</World>
How do I get all elements under tag where id == 1?
My Linq query. (doesn't work) why?
XDocument xml= XDocument.Load(xml.xml);
var elements = from e in xml.Descendants("Animals").Descendants("Tab").Elements("Dogs")
where e.Attribute("id").toString().Equals("1")
select c;
Could you check it please?
Thanks!
var result = xdoc.Descendants("World")
.Descendants("Animals")
.Descendants("Tab")
.Elements("Dogs")
.Where(n => n.Attribute("id").Value == "1");
Output:
<Dogs id="1">
<Dog1></Dog1>
<Dog2></Dog2>
<Dog3></Dog3>
</Dogs>
Or use XPath:
xml.XPathSelectElements("/World/Animals/Tab/Dogs[#id=1]")
or
xml.XPathSelectElements("//Dogs[#id=1]")
which would find all Dogs wherever they occurred.
From your sample data I think you want
//from e in xml.Descendants("Animals").Descendants("Tab").Elements("Dogs")
from e in xml.Descendants("Animals").Elements("Tab").Descendants("Dogs")
And in the same line, Descendants("Animals") could be Elements("Animals") if you want to enforce the structure.
For the rest your query looks OK.

Categories

Resources