XML Parsing through LINQ - c#

I am doing my web service project using WCF. The problem is that I have an XML file which is like this:
<Cars>
<Make Name="Honda">
<Model Name="Accord" Year="2013">
<Price>22480</Price>
</Model>
<Model Name="Civic" Year="2013">
<Price>17965</Price>
</Model>
<Model Name="Crosstour" Year="2013">
<Price>27230</Price>
</Model>
<Model Name="CR-V" Year="2013">
<Price>22795</Price>
</Model>
</Make>
</Cars>
I want to retrieve the Price for the given Model where the Name attribute is supplied by the user. I am using this Approach:
var DBCodes = from Cars in XmlEdit.Descendants("Cars")
from Make in Cars.Elements("Make")
from Made in Make.Elements("Made")
where Made.Attribute("Name").Value == CarName //Variable for Name
select Make;
foreach (var Make in DBCodes)
{
if (Make != null)
PriceOfCar = Make.Element("Price").Value.ToString();
else
break;
}
But its not working. Where am I making the mistake?

var cars =
XDocument.Load("a.xml")
.Descendants("Make")
.Select(make => new
{
Name = make.Attribute("Name").Value,
Models = make.Descendants("Model")
.Select(model => new{
Name = (string)model.Attribute("Name"),
Year = (int)model.Attribute("Year"),
Price = (int)model.Element("Price")
})
.ToList()
})
.ToList();
string userInput="Civic";
var price = cars.SelectMany(c => c.Models).First(m => m.Name == userInput).Price;
You can even get the price directly from xml without converting it into an temporary structure
string userInput="Civic";
var price = (int)XDocument.Load("a.xml")
.Descendants("Model")
.First(m => (string)m.Attribute("Name") == userInput)
.Element("Price");

Related

How to Display the XML data to a GRIDVIEW

i have this following XML file
<personaldetails>
<name>ravi</name>
<id>1</id>
<branch>CSE</branch>
</personaldetails>
<professionaldetails>
<name>ravi</name>
<age>25</age>
<gender>male</gender>
</professionaldetails>
This is the sample data .so,now when i search with a name "ravi" in textbox it should display both tables i.e; personal and professional.how to do this using DATATABLE and bind it to GRIDVIEW.
Am doing this in ASP.NET using C#
How can we solve this issue using c#
or
can we do this using LINQ QUERIES
You might use Linq To XML with a valid XML. ie:
string sXML = #"<root>
<personaldetails>
<name>ravi</name>
<id>1</id>
<branch>CSE</branch>
</personaldetails>
<professionaldetails>
<name>ravi</name>
<age>25</age>
<gender>male</gender>
</professionaldetails>
</root>";
var prd = XElement
.Parse(sXML)
.Descendants()
.Where(xe => xe.Name=="professionaldetails" && (string)xe.Element("name") == "ravi")
.Select(p => new {
Name = (string)p.Element("name"),
Age = (int?)p.Element("age"),
Gender = (string)p.Element("gender")
}) ;

Get XML nodes attributes and set as properties of List<myType>?

Example XML:
<Root>
<Product value="Candy">
<Item value="Gum" price="1.00"/>
<Item value="Mints" price="0.50"/>
</Product>
</Root>
Let's say I have a class with properties:
public class CandyItems
{
public string Value{get; set;}
public string Price{get; set;}
}
And within my main program class, I have a list:
var Candies = new List<CandyItems>;
I am struggling with a concise way to populate the Candies list, using LINQ.
I could do it in steps, like this:
//Get list of Items within <Product value="Candy">
XElement tempCandies = XDocument.Load("file.xml").Root.Elements("Product").Single(c => c.Attributes("value") == "Candy").Descendants("Item");
//Loop through the elements
foreach(var item in tempCandies){
Candies.Add(new CandyItems{Value = item.Attributes("value"), Price = item.Attributes("price")});
}
But it seems like I could do this more concisely with pure LINQ somehow. Or is there another recommended method?
Try this:-
XDocument xdoc = XDocument.Load(#"Path\Candies.xml");
List<CandyItems> Candies = xdoc.Descendants("Item")
.Select(x => new CandyItems
{
Value = (string)x.Attribute("value"),
Price = (string)x.Attribute("price")
}).ToList();
Although, you have not mentioned but if you want to just fetch Candies and your XML may contain other products too like:-
<Root>
<Product value="Candy">
<Item value="Gum" price="1.00"/>
<Item value="Mints" price="0.50"/>
</Product>
<Product value="Chocolate">
<Item value="MilkChocolate" price="7.00"/>
<Item value="DarkChocolate" price="10.50"/>
</Product>
</Root>
Then you can apply a filter to fetch only Candy products like this:-
List<CandyItems> Candies = xdoc.Descendants("Item")
.Where(x => (string)x.Parent.Attribute("value") == "Candy")
.Select(x => new CandyItems
{
Value = (string)x.Attribute("value"),
Price = (string)x.Attribute("price")
}).ToList();
How about something like this (after loading the document):
var candies =
xdoc.Root.Elements("Product")
.Where(p => p.Attribute("value").Value == "Candy")
.SelectMany(p => p.Descendants("Item").Select(i => new CandyItems {
Value = i.Attribute("value").Value,
Price = i.Attribute("price").Value }));
Note: any and all error handling omitted.

How I can filter my xml to a search value?

hi I want to translate my site for this I use a Xml file and with Linq to xml I want to get the value. here is my xml for example:
<?xml version="1.0" encoding="utf-8"?>
<Languages>
<values id="_hallo">
<value value="DE" display="Hallo"></value>
<value value="EN" display="Hello"></value>
<value value="CS" display="Tschechisch"></value>
<value value="ES" display="Spanisch"></value>
<value value="ZH" display="德國的"></value>
</values>
</Languages>
here is my c#:
private void SiteTranslate(string language)
{
string BrowserLanguage = Request.UserLanguages[0].ToString().Substring(0, 2).ToUpper(); // here I get "DE" or "EN" etc..
string btnadd_id = "_hallo"; // for example
XDocument x = XDocument.Load(Server.MapPath(#"~\App_Data\SiteLanguage.xml"));
string val = from tep in x.Descendants("values").Where(el => el.Attribute("id").Value == btnadd_id).
Descendants("value").
Where(l => l.Attribute("value").Value == language).Select //?????? :(
BtnAdd.Text = val;
}
It's a simple "get the one and only element" problem:
string val = x.Descendants("values")
.Where(el => el.Attribute("id").Value == btnadd_id)
.Elements("value")
.Where(l => l.Attribute("value").Value == language)
.SingleOrDefault()
.Attribute("display").Value;

Not able to select relevant nested nodes: LINQ

My sample XML is something like this:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<RoleSecurity Name="A" Workflowstatus ="B">
<Accountgroup Name = "Group1">
<Attribute ID="12345" Name="Sample1"/>
<Attribute ID="12445" Name="Sample2"/>
</Accountgroup>
<Accountgroup Name = "Group2">
<Attribute ID="12345" Name="Sample1"/>
<Attribute ID="12445" Name="Sample2"/>
</Accountgroup>
</RoleSecurity>
</Root>
I am trying to enumerate and extract all the ID corresponding to a particular Role name, workflow status and account group.
My LINQ query is working to select a node based on role name. But I am unable to proceed further.
Please help!
This is my LINQ code till now.
XElement xcd = XElement.Load(strFileName);
IEnumerable<XElement> enumCust = from cust in xcd.Elements("RoleSecurity")
where (string)cust.Attribute("Name") == strRole
select cust;
Try this:
string roleName = "A";
string workflowStatus = "B";
string accountGroup = "Group1";
string xml = #"<?xml version=""1.0"" encoding=""utf-8""?>
<Root>
<RoleSecurity Name=""A"" Workflowstatus =""B"">
<Accountgroup Name = ""Group1"">
<Attribute ID=""12345"" Name=""Sample1""/>
<Attribute ID=""12445"" Name=""Sample2""/>
</Accountgroup>
<Accountgroup Name = ""Group2"">
<Attribute ID=""12345"" Name=""Sample1""/>
<Attribute ID=""12445"" Name=""Sample2""/>
</Accountgroup>
</RoleSecurity>
</Root>";
XElement element = XElement.Parse(xml);
var ids = element.Elements("RoleSecurity")
.Where(
e =>
(string) e.Attribute("Name") == roleName &&
(string) e.Attribute("Workflowstatus") == workflowStatus)
.Elements("Accountgroup").Where(e => (string) e.Attribute("Name") == accountGroup)
.Elements("Attribute")
.Select(e => new {ID = (string) e.Attribute("ID"), Name = (string) e.Attribute("Name")});
Try with this approach, seems different from your (and in some aspects it really changes), but in my opinion its a good way to use fluently a LINQ query to parse an XML file, it follows XML node sequence and it's easy to understand:
XElement element = XElement.Load(strFileName);
var linqList = element.Elements("RoleSecurity")
.Where(entry => entry.Attribute("Name").Value == "A" &&
entry.Attribute("Workflowstatus").Value == "B")
.Descendants("Accountgroup")
.Where(x => x.Attribute("Name").Value == "Group1")
.Descendants("Attribute")
.SelectMany(id => id.Attribute("ID").Value);
XElement xcd = XElement.Load(strFileName);
IEnumerable<XElement> enumCust = from cust in xcd.Root.Elements("RoleSecurity")
where cust.Attribute("Name").Value == strRole
select cust;
This should work now
you were missing .Root which is required to enumerate below the root node
and .Value to retrive the string value of the specified attribute
refer this artical :- http://www.dotnetcurry.com/ShowArticle.aspx?ID=564
foreach (XElement xcd xelement.Descendants("Id"))
{
Console.WriteLine((string)xcd);
}

Retrieving Multiple Items from an XML File using LINQ to XML with C#

I'm new to LINQ to XML and I'm having problems writing C# to retrieve multiple items from an XML file, i.e. in the code sample below. I would like to go through the file and retrieve each OrderProduct id=??? and get the information in Quantities and Product. I can retrieve a single order only, but not if more than one is in the file.
This is the C# code I'm using which only retrieves the first order.
xelement = XElement.Load (orderXML);
IEnumerable<XElement> OrderXml = xelement.Elements ();
foreach (var order in OrderXml.Elements ("OrderProducts"))
{
m_productOrderID = order.Element ("OrderProduct").Attribute ("id").Value;
m_productName = order.Element ("OrderProduct").Element ("Product").Element ("Name").Value;
m_productCatalogNumber = order.Element ("OrderProduct").Element ("Product").Element ("CatalogNumber").Value;
m_productQuantity = order.Element ("OrderProduct").Element ("Quantities").Element ("NumberOfCopies").Value;
}
The XML file:
<?xml version="1.0" encoding="utf-16"?>
<OrderXml>
<Order>
<OrderProducts>
<OrderProduct id="569">
<Quantities>
<NumberOfRecipients>1</NumberOfRecipients>
<NumberOfCopies>1</NumberOfCopies>
<TotalUnits>1</TotalUnits>
</Quantities>
<Product id="444">
<Name>Product 1</Name>
<CatalogNumber>20130621-001</CatalogNumber>
</Product>
</OrderProduct>
<OrderProduct id="570">
<Quantities>
<NumberOfRecipients>1</NumberOfRecipients>
<NumberOfCopies>100</NumberOfCopies>
<TotalUnits>100</TotalUnits>
</Quantities>
<Product id="258">
<Name>Product 2</Name>
<CatalogNumber>20130621-002</CatalogNumber>
</Product>
</OrderProduct>
</OrderProducts>
</Order>
</OrderXml>
from op in xdoc.Descendants("OrderProduct")
let q = op.Element("Quantities")
let p = op.Element("Product")
select new {
Id = (int)op.Attribute("id"),
Quantities = new {
NumberOfRecipients = (int)q.Element("NumberOfRecipients"),
NumberOfCopies = (int)q.Element("NumberOfCopies"),
TotalUnits = (int)q.Element("TotalUnits")
},
Product = new {
Id = (int)p.Attribute("id"),
Name = (string)p.Element("Name"),
CatalogNumber = (string)p.Element("CatalogNumber")
}
}
Then getting single order product:
var orderProduct = query.FirstOrDefault(x => x.Id == yourId);
if (orderProduct != null)
// ...
Getting all ids:
var ids = xdoc.Descendants("OrderProduct")
.Select(op => (int)op.Attribute("id"));
BTW Next time provide code which you already have

Categories

Resources