Xdocument getting element node value from another note in the xml file - c#

I'm trying to get some data from an XML file - see below.
Basically for each session data, I get all the elements in it and store it but I need to get the movie_Name from the elements with reference by the movie.
<Schedule_Data>
<Movies>
<Movie>
<Cinema_ID>3169101</Cinema_ID>
<Movie_ID>1012689</Movie_ID>
<Movie_Name>2D Captain America: Civil War</Movie_Name>
<Rating>PG13</Rating>
<Runtime>160</Runtime>
</Movie>
<Movie>
<Cinema_ID>3169101</Cinema_ID>
<Movie_ID>1012984</Movie_ID>
<Movie_Name>2D Zootopia</Movie_Name>
<Rating>PG</Rating>
<Runtime>115</Runtime>
</Movie>
</Movies>
<Sessions>
<Session>
<Cinema_ID>8888888</Cinema_ID>
<Movie_ID>1012689</Movie_ID>
<Session_ID>1083592422</Session_ID>
<Price_group_code>10007</Price_group_code>
<Auditorium_Number>9</Auditorium_Number>
<Assigned_Seating>True</Assigned_Seating>
<Attribute></Attribute>
<Date_time>20160607141000</Date_time>
<Total_Seats>87</Total_Seats>
<Available_Seats>87</Available_Seats>
</Session>
<Session>
<Cinema_ID>8888888</Cinema_ID>
<Movie_ID>1012984</Movie_ID>
<Session_ID>1083592423</Session_ID>
<Price_group_code>10007</Price_group_code>
<Auditorium_Number>9</Auditorium_Number>
</Session>
</Sessions>
</Schedule_Data>
Currently my code is:
XDocument thisXML = XDocument.Parse(responseText);
//get the dates element (which contains all the date nodes)
XElement datesElement = thisXML.Element("Schedule_Data").Element("Sessions");
//use linq to compile an ienumerable of the date nodes
var dates = from dateNode in datesElement.Elements("Session")
select dateNode;
//get the dates element (which contains all the film nodes)
XElement MoviesElement = thisXML.Element("Schedule_Data").Element("Movies");
foreach (XElement session in dates)
{
//get movie name
var films = from filmnode in MoviesElement.Elements("Movie")
select filmnode;
var movieId = session.Element("Movie_ID").Value;
// This is where i try do the where clause and try get the value but it returns null
var answer = from reply in films
where reply.Element("Movie_ID").Value == movieId
select films.Elements("Movie_Name");
//create a new session import record
ORM.Sessionimportattemptimportedsession newSessionimportattemptimportedsession = new ORM.Sessionimportattemptimportedsession();
//check data and set properties
newSessionimportattemptimportedsession.MovieTitle = answer.ToString();
newSessionimportattemptimportedsession.ScreenNumber = session.Element("Screen_bytNum").Value;
.....
numberOfSessions++;
}
Any suggestions?

You're just performing a join between sessions and movies. Just do this:
var query =
from s in doc.Descendants("Session")
join m in doc.Descendants("Movie")
on (string)s.Element("Movie_ID") equals (string)m.Element("Movie_ID")
select new
{
MovieName = (string)m.Element("Movie_Name"),
Session = s,
Movie = m,
};

Related

C# XML linq query

Hi I have the following XML:
<EPICORTLOG>
<POS>
<ClientId>WkStn.90.1</ClientId>
<Id>POS.90.20140819.251.8279</Id>
<StartTime>2014-08-25T05:12:34</StartTime>
<Store>90</Store>
<SysDate>2014-08-19T00:00:00</SysDate>
<TillNo>1</TillNo>
<Time>2014-08-25T05:12:34</Time>
<Tran>1093</Tran>
<WkStn>1</WkStn>
<WORKSTATION>
<IsAutoLock>1</IsAutoLock>
</WORKSTATION>
<TRADE>
<ITEM>
<Class>102499</Class>
<Desc>NIKE RACER</Desc>
<FinalPrice>82.77</FinalPrice>
<Status>ACTV</Status>
<Style>EV0615</Style>
<Tag>1</Tag>
</ITEM>
</TRADE>
</POS>
</EPICORTLOG>
There are many POS nodes like above in the actual XML. I am trying to fetch the POS node with ID=POS.90.20140819.251.8279 and then the details of Item from that particular node. I have written the following query:
XDocument xdoc = XDocument.Load(XMLFile);
var item = from items in xdoc.Element("EPICORTLOG").Descendants("POS")
where items.Attribute("Id").Value == strSelectedPOSID
select new
{
desc=items.Element("ITEM").Attribute("Desc")
};
But it is not yielding any result for me. Here strSelectedPOSID=POS.90.20140819.251.8279. Please let me know where i am going wrong.
Id and Desc are not an Attributes. they are Elements so you should use
var item = from items in xdoc.Descendants("POS")
where (string)items.Element("Id") == strSelectedPOSID
select new
{
desc = (string)items.Element("ITEM").Element("Desc")
};
I got the value at last!! Following is what i used:
var item = from items in xdoc.Element("EPICORTLOG").Descendants("POS")
where (string)items.Element("Id") == strSelectedPOSID
select new
{
desc = items.Element("TRADE").Element("ITEM").Element("Desc").Value.ToString()
};
Thanks for the inputs.

Extracting XML values from two nodes

I want to extract the value in the moduleId attibute and the value from the Field node. For example, in this first node I want to extract the 447 in the moduleId and the 124694 from the Field node. I have the XML loaded in an XDocument. The end result will be a Tuple where the first item is the value from the moduleId attribute and the second item is the value from the Field node. Is there a way I can do this using one XLinq statement?
As a bonus...I only want to do it for nodes where the guid = "07a188d3-3f8c-4832-8118-f3353cdd1b73". This part I can probably figure out if someone can tell me how to extract information from two nodes, but a bonus would be to add the WHERE clause in there for me :)
<Records>
<Record moduleId="447">
<Field guid="07a188d3-3f8c-4832-8118-f3353cdd1b73">124694</Field>
</Record>
<Record moduleId="447">
<Field guid="07a188d3-3f8c-4832-8118-f3353cdd1b73">124699</Field>
</Record>
<Records>
I have gotten as far as extracting the Field value using this...
IEnumerable<string> c = from p in sourceDocument.Descendants("Field")
where p.Attribute("guid").Value == "07a188d3-3f8c-4832-8118-f3353cdd1b73"
select p.Value;
But I have no idea how to get information from both the Record node and the Field node.
Give this a try:
var doc = XDocument.Parse(xml);
var r = doc.Descendants("Record")
.Where(n => n.Element("Field").Attribute("guid").Value == "07a188d3-3f8c-4832-8118-f3353cdd1b73")
.Select(n => new { ModuleId = n.Attribute("moduleId").Value, Field = n.Element("Field").Value });
var a = r.ToArray();
Here is a solution that uses LINQ Query Syntax:
XDocument document = XDocument.Parse(xml);
var query =
from el in document.Root.Elements("Record")
where (string)el.Element("Field").Attribute("guid") ==
"07a188d3-3f8c-4832-8118-f3353cdd1b73"
select new
{
ModuleId = (string)el.Attribute("moduleId"),
Field = (string)el.Element("Field")
};
foreach (var item in query)
{
Console.WriteLine
("ModuleId:[{0}]\nField:[{1}]\n--",
item.ModuleId,
item.Field);
}

simple way to read xml data using linq

I have a xml structure like this. Can anyone help with a simple linq function to read this xml structure.The itemEntry node repeats according to data. I tried to read the xml using the method below,but i am getting no records in the list. Is this method here correct way to get the details...
List<CX_ITEMLIST> sList =
(from e in XDocument.Load(param.FileName).Root.Elements("itemEntry")
select new CX_ITEMLIST
{
TITLE = (string)e.Element("title"),
YEAR = (string)e.Element("year"),
ITEMNAME = (string)e.Element("itemname"),
CATRYLIST =
(
from p in e.Elements("categorylist").Elements("categories")
select new CATLIST
{
IDTYPE = (string)p.Element("categoryid"),
IDNUMBER = (string)p.Element("categoryName")
}).ToList()
}).ToList();
<itemslist>
<itemInformation>
<itemdate>01/23/2014</itemdate>
<itemcount>57</itemcount>
</itemInformation>
<itemEntry>
<title>Title1</title>
<year>2013</title>
<itemname>testname</itemname>
<categorylist>
<categories>
<categoryid>Category1</categoryid>
<categoryName>Category2</categoryName>
</categories>
<categories>
<categoryid>Category1</categoryid>
<categoryName>Category2</categoryName>
</categories>
</categorylist>
</itemEntry>
<itemEntry>
<title>Title1</title>
<year>2013</title>
<itemname>testname</itemname>
<categorylist>
<categories>
<categoryid>Category1</categoryid>
<categoryName>Category2</categoryName>
</categories>
<categories>
<categoryid>Category1</categoryid>
<categoryName>Category2</categoryName>
</categories>
</categorylist>
</itemEntry>
</itemslist>
You should try with XDocument.
XDocument xdoc = XDocument.Load("file.xml");
The System.Xml.XLinq namespace contains some awesome objects to make this easy.
var xDoc = XDocument.Parse(xml); // load your xml string, or use XDocument.Load() to load an xml file
var itemEntries = xDoc
.Root // refers to itemEntries node
.Descendants("itemEntry"); // gets all itemEntry nodes in an IEnumerable object
This gets you an IEnumerable<XNode> of all the itemEntry nodes.
From there you can do what you need, save the values to a business object, etc.
The above method works properly, i found the issue, my xml tag was having namespace attribute. i tried to get the namespace and append it with Elements while reading
XNamespace ns = xDocument.Root.Attribute("xmlns").Value;
List<CX_ITEMLIST> sList =
(from e in XDocument.Load(param.FileName).Root.Elements(ns + "itemEntry")
select new CX_ITEMLIST
{
TITLE = (string)e.Element(ns + "title"),
YEAR = (string)e.Element(ns + "year"),
ITEMNAME = (string)e.Element(ns + "itemname"),
CATRYLIST =
(
from p in e.Elements(ns + "categorylist").Elements(ns + "categories")
select new CATLIST
{
IDTYPE = (string)p.Element(ns + "categoryid"),
IDNUMBER = (string)p.Element(ns + "categoryName")
}).ToList()
}).ToList();

Find a child node and get the value of it using a variable. Windows phone

So i am able to select all the results under a certain node, but I have the following XML
<ArrayOfStop>
<Stop>
<StopName>Rajdutt Restaurant</StopName>
<route_stop />
<route_stop_stop />
<route_stop_timetable_stop />
<stopId>6400</stopId>
</Stop>
<Stop>
<StopName>Cysleys Farm (by request only)</StopName>
<route_stop />
<route_stop_stop />
<route_stop_timetable_stop />
<stopId>6401</stopId>
</Stop>
<ArrayOfStop>
If i want to select stopId if the stopname was Cysleys Farm (by request only) how would one go about it?
I have the following code:
XDocument loadedData = XDocument.Load("People.xml");
var data = from query in loadedData.Descendants("ArrayOfStop")
select new Person
{
StopName = (string)query.Element("StopName")
};
listBox.ItemsSource = data;
EDIT:
var data = from query in loadedData.Descendants("ArrayOfStop")
where query.Element("StopName").Value == "Cysleys Farm (by request only)"
select query.Element("StopId").Value;
select new Person
{
FirstName = (string)query.Element("StopName"),
//LastName = (string)query.Element("Long"),
//Age = (int)query.Element("age")
};
listBox.ItemsSource = data;
EDIT 2
Do the items need to be going into a list box? As i need the value in a string format to use on a url.
var doc =
XDocument.Parse(
"<ArrayOfStop><Stop><StopName>Rajdutt Restaurant</StopName><route_stop /><route_stop_stop /><route_stop_timetable_stop /><stopId>6400</stopId></Stop><Stop><StopName>Cysleys Farm (by request only)</StopName><route_stop /><route_stop_stop /><route_stop_timetable_stop /><stopId>6401</stopId></Stop></ArrayOfStop>");
var list = (from item in doc.Descendants("Stop")
where (string) item.Element("StopName") == "Cysleys Farm (by request only)"
select (string)item.Element("stopId")).ToList();
This will get you a single node that has a matching value. If you expect more than one node will have a matching value and only want the first one, then use FirstOrDefault instead of SingleOrDefault.
string search = "Cysleys Farm (by request only)";
var query = doc.Root.Elements()
.SingleOrDefault( x => x.Element( "StopName" ).Value == search );
if (query != null)
{
// if the query is not null, then this will be
// a single node with a root of <Stop>
string id = query.Element( "stopId" ).Value;
}
Another way of doing it is:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("People.xml");
// Select the 'StopId' node whose StopName is 'Cysleys Farm (by request only)'
XmlNode stopIdNode = xmlDoc.SelectSingleNode("/ArrayOfStop/Stop[StopName='Cysleys Farm (by request only)']/stopId");
string stopId = stopIdNode.InnerText;
If there are multiple nodes with the same StopName, then you can store them in a list:
List<string> stopIdList = new List<string>();
foreach (XmlNode stopIdNode
in xmlDoc.SelectNodes
("/ArrayOfStop/Stop[StopName='Cysleys Farm (by request only)']/stopId"))
{
stopIdList.Add(stopIdNode.InnerText);
}

Filtering your LINQ to XML query

I have the following:
XDocument xdoc = XDocument.Load("C:\\myfile.xml");
List<Tag> list = new List<Tag>();
foreach (var tag in xdoc.Descendants("META"))
{
string name = tag.Attribute("name").Value;
string value = tag.Element("value").Value;
list.Add(new Tag { Name = name, Value = value, Score = score, Key = key });
}
but I need to only get the META elements under the element ARTICLE.
Can I add this to the linq query somehow?
The xml looks similar to this:
<DOCUMENT>
<META name="aaa"/>
<ARTICLE>
<META name="bbb" value="708" score="0.58" key="6008"/>
</ARTICLE>
</DOCUMENT>
Thanks for any suggestions
In the end I need to do something like the following:
XDocument xdoc = XDocument.Load(tr);
var meta = from el in xdoc.Descendants("ARTICLE").Elements("META")
where (string) el.Attribute("name") == "RAW"
select el;
List<Tag> list = new List<Tag>();
foreach (var tag in meta)
{
string name = tag.Attribute("name").Value;
string value = tag.Attribute("value").Value;
string score = tag.Attribute("score").Value;
string key = tag.Attribute("key").Value;
list.Add(new Tag { Name = name, Value = value, Score = score, Key = key });
}
The reason for this is that I needed to match the attribute where the name was equal to RAW.
Please correct me if there's a better way to do this!
To find them anywhere in the document, use xdoc.Descendants("ARTICLE") to find all the ARTICLE elements, and then Elements("META") from there to find all the direct META children elements.
In addition, you can perform the projection and the conversion to a list in the same query:
var list = xdoc.Descendants("ARTICLE")
.Elements("META")
.Select(x => new Tag { Name = (string) x.Attribute("name"),
Value = (string) x.Attribute("value"),
Key = key })
.ToList();

Categories

Resources