Not able to select relevant nested nodes: LINQ - c#

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);
}

Related

how to print the innertext of an element based on attribute search of a particular node using LINQ?

**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".**

Getting specific data in node by other data in same node

I got XML like that:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!--Some comment-->
<Databook>
<Note>
<Name>Camera2 made a snapshoot #243</Name>
<Value>Camera2_snapshoot-2013-09-06_21-47-35.png</Value>
</Note>
<Note>
<Name>Camera1 made a snapshoot #244</Name>
<Value>Camera1_snapshoot-2013-09-06_21-47-39.png</Value>
</Note>
</Databook>
And i want to get string beetwen [Value]..[/Value] of specific node, knowing only it's string of [Name]..[/Name].
This what i did so far:
string xmlfile = string.Format("XML/Diary/" + day);
XDocument dailyXML = XDocument.Load(xmlfile);
XElement Contact = (from xml2 in dailyXML.Descendants("Note")
where xml2.Element("Name").Value == item
select xml2).FirstOrDefault();
You are very close, if you just want the value of Value where the Name equals item
Try:
string result = (from xml2 in dailyXML.Descendants("Note")
where xml2.Element("Name").Value == item
select xml2.Element("Value").Value).FirstOrDefault();
or
string result = dailyXML.Descendants("Note")
.Where(n => n.Element("Name").Value == item)
.FirstOrDefault(n => n.Element("Value").Value);

XML Parsing through LINQ

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");

Get XML values from XML database string in C#

I’m trying to get the values of an xml snippet that is stored in my database but can’t seem to make it work. They are all coming back null... The xml looks like this:
<fields>
<field id="EmployeeID">1002240002</field>
<field id="JobType">Web Manager</field>
<field id="CompanyCode">R6297C</field>
</fields>
My Code, with the string from the database is below.
string xml = "<fields><field id=\"EmployeeID\">1002240002</field><field id=\"JobType\">Web Manager</field><field id=\"CompanyCode\"> R6297C </field></fields>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
var n = xmlDoc.GetElementById("EmployeeID ");
if (n != null)
{
var employeeId = xmlDoc.GetElementById("EmployeeID ").InnerText;
}
Any help on this? I know I am missing something easy here... Thanks!
You can use following XPath query
string xpath = "field[#id='EmployeeID']";
XmlNode fieldNode = xmlDoc.DocumentElement.SelectSingleNode(xpath);
var id = Int32.Parse(fieldNode.InnerText);
Or Linq to Xml
var id = (from f in xdoc.Descendants()
where (string)f.Attribute("id") == "EmployeeID"
select (int)f).Single();
Or with fluent interface
var id = xdoc.Descendants()
.Where(f => (string)f.Attribute("id") == "EmployeeID")
.Select(f => (int)f)
.Single();
BTW xdoc is an instance of XDocument class:
var xdoc = new XDocument(xml);

Search XML doc with LINQ

I have an xml doc similar to this:
<Root>
<MainItem ID="1">
<SubItem></SubItem>
<SubItem></SubItem>
<SubItem></SubItem>
</MainItem>
<MainItem ID="2">
<SubItem></SubItem>
<SubItem></SubItem>
<SubItem></SubItem>
</MainItem>
...
</Root>
I want to return the whole of the MainItem element based on the value of attribute ID.
So effectively if Attribute ID is equal to 2, then give me that MainItem element back.
I can't work out how to do this with LINQ.
There seems to be a load of information on google, but I just can't quite seem to find what I'm looking for.
Little help ?
TIA
:-)
It could be something like this:
XDocument doc = XDocument.Load("myxmlfile.xml");
XElement mainElement = doc.Element("Root")
.Elements("MainItem")
.First(e => (int)e.Attribute("ID") == 2);
// additional work
How about this:
// load your XML
XDocument doc = XDocument.Load(#"D:\linq.xml");
// find element which has a ID=2 value
XElement mainItem = doc.Descendants("MainItem")
.Where(mi => mi.Attribute("ID").Value == "2")
.FirstOrDefault();
if(mainItem != null)
{
// do whatever you need to do
}
Marc
I changed your XML slightly to have values:
<?xml version="1.0"?>
<Root>
<MainItem ID="1">
<SubItem>value 1</SubItem>
<SubItem>val 2</SubItem>
<SubItem></SubItem>
</MainItem>
<MainItem ID="2">
<SubItem></SubItem>
<SubItem></SubItem>
<SubItem></SubItem>
</MainItem>
</Root>
And with this LINQ:
XDocument xmlDoc = XDocument.Load(#"C:\test.xml");
var result = from mainitem in xmlDoc.Descendants("MainItem")
where mainitem.Attribute("ID").Value == "1"
select mainitem;
foreach (var subitem in result.First().Descendants())
{
Console.WriteLine(subitem.Value);
}
Console.Read();
From here: How to: Filter on an Attribute (XPath-LINQ to XML)
// LINQ to XML query
IEnumerable<XElement> list1 =
from el in items.Descendants("MainItem")
where (string)el.Attribute("ID") == "2"
select el;
// XPath expression
IEnumerable<XElement> list2 = items.XPathSelectElements(".//MainItem[#ID='2']");

Categories

Resources