parse xml - get youtube description from videos in playlist - c#

Im trying to get the description of a youtube video from a youtube playlist.
the xml playlist looks something like this:
<entry gd:etag="W/"YhjhqeyM."">
<title>My Title</title>
<media:group>
<media:description type="plain">My description</media:description>
</media:group>
</entry>
.
.
.
...multiple entry elements
I'm looping through the multiple entries and getting the title like so:
var x = (from e in xmlFeed.Root.Elements().Where(n => n.Name.LocalName == "entry") select e);
foreach (XElement element in x)
{
title = element.Elements().Where(n => n.Name.LocalName == "title").FirstOrDefault().Value;
description = //??;
}
How can i get the description given the above format?
Thanks

description = element.Descendants(XName.Get("description")).First().Value();

This does it, it's up to you how you're loading in your doc though. I've read it in with a HttpWebRequest/StreamReader in this case:
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.Load(requestData("https://gdata.youtube.com/feeds/api/playlists/63F0C78739B09958?v=2"));
var node = doc.DocumentNode.Descendants("media:description").ToList();
foreach (var description in node)
{
Response.Write(string.Format("Description: {0}\n",description.InnerText.ToString()));
}

XDocument xDoc = XDocument.Load("https://gdata.youtube.com/feeds/api/playlists/63F0C78739B09958?v=2");
XNamespace media = XNamespace.Get("http://search.yahoo.com/mrss/");
var descs = xDoc.Descendants(media + "description")
.Select(d => d.Value)
.ToArray();

Related

Linq to XML elements

Hi I try to read an xml file with LINQ.
The name of the file is:categorizedBooks.xml
and the content of the file looks like this:
<category name=".NET">
<books>
<book>CLR via C#</book>
<book>Essential .NET</book>
</books>
</category>
The code for reading the file looks like this:
XElement rootss = XElement.Load(#"D:/categorizedBooks.xml");
XElement dotNetCategoryss = rootss.Element("category");
XAttribute namehallo = dotNetCategoryss.Attribute("name");
XElement booksss = dotNetCategoryss.Element("books");
IEnumerable<XElement> bookElements = booksss.Elements("book");
Console.WriteLine((string)dotNetCategoryss);
foreach (XElement bookElement in bookElements)
{
Console.WriteLine(" - " + (string)bookElement);
}
But i get null on this line:
XAttribute namehallo = dotNetCategoryss.Attribute("name");
So how to fix this , so that it not will be null?
Thank you
Your doc root is the category element - try:
XAttribute namehallo = rootss.Attribute("name");
Console.WriteLine(namehallo.Value);
You'll have to change your other XElement references similarly
instead of XElement.Load use XDocument.Load or XDocument.Parse
var xml = #"
<category name='.NET'>
<books>
<book>CLR via C#</book>
<book>Essential .NET</book>
</books>
</category>";
var document = XDocument.Parse(xml);
// returns: .NET
var category = document
.Element("category")
.Attributes("name")
.Select(p => p.Value);
// returns: CLR via C#, Essential .NET
var books = document
.Descendants("book")
.Select(p => p.Value);

C# reading xml inside certain node

I need help. I'm trying to figure out a way to read inside a bracket like this one:
<group id = "56">
<name>Counter</name>
</group>
In the code, there are mulitiple places where the same pattern comes back, and I would like to get all the group id number's and their name.
This is my code:
XDocument doc = XDocument.Parse(_XmlFile);
var results = doc.Descendants("group").Select(x => new
{
id = (int)x.Attribute("id"),
name = x.Attribute("name").Value,
}).ToList();
Console.WriteLine(results);
Thanks
Your code looks quite OK, but name is an element and not an attribute, so it should be
XDocument doc = XDocument.Parse(_XmlFile);
var results = doc.Descendants("group").Select(x => new
{
id = (int)x.Attribute("id"),
name = (string)x.Element("name"),
}).ToList();
foreach (var x in results)
Console.WriteLine("id: {0} name: {1}", x.id, x.name);
Use GetElementsByTagName method.
Here is the microsoft article explaining it with examples.
https://msdn.microsoft.com/en-us/library/dc0c9ekk(v=vs.110).aspx
"Name" is not an attribute, but a child node. The solution is something like this:
XDocument doc = XDocument.Parse(_XmlFile);
var results = doc.Descendants("group").Select(x => new
{
id = int.Parse(x.Attribute("id").Value),
name = x.Descendants("name").First().Value
}).ToList();

C# split xml innertext or parse innerxml

I have an XML file with a structure similar to this
<entry name="something">
<members>
<member>aaa</member>
<member>bbb</member>
</members>
</entry>
<entry name="something_else">
<members>
<member>ccc</member>
<member>ddd</member>
</members>
</entry>
I need to be able to get the values out of each of the member nodes to store in a datatable. if i use the innertext property, it concatenates the values (aaabbb). there is nothing discernible to split the string on. I can also use the inner XML but then i just get a string with the XML structure (aaa bbb<\member>)
What is the best way to get each value out of the XML elements and store it in a string array?
here is what I have been trying.
foreach (XmlNode grpNode in GrpList)
{
subNode = grpNode.Attributes["name"];
if (subNode != null)
{
Obj = grpNode.Attributes["name"].Value;
}
subNode = grpNode["members"];
if (subNode != null)
{
string innerXml = string.Empty;
innerXml = grpNode["members"].InnerXml.ToString();
string[] tempArrary = innerXml.Split(new char[] {'>', '<'});
}
}
You can use Xpath to iterate through Entry nodes and get the members within it like this
string xml = "<root><entry name='something'>" +
"<members>" +
"<member>aaa</member>" +
"<member>bbb</member>" +
"</members>" +
"</entry>" +
"<entry name='something_else'>" +
"<members>" +
"<member>ccc</member>" +
"<member>ddd</member>" +
"</members>" +
"</entry></root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var memsList = doc.SelectNodes("//entry");
foreach (XmlNode a in memsList)
{
Console.WriteLine(a.Attributes["name"].Value);
var memList = a.SelectNodes("members/member");
foreach(XmlNode x in memList)
Console.WriteLine(x.InnerText);
}
You need to iterate the child elements within members, so something like:
foreach (var node in grpNode["members"].ChildNodes)
{
var value = node.InnerText;
}
That said, you would be better off using LINQ to XML unless you have some specific reason to use XmlDocument. This gives you much more expressive code, for example:
var doc = XDocument.Parse(xml);
var something = doc.Descendants("entry")
.Where(e => (string)e.Attribute("name") == "something")
.Single();
var somethingMembers = something.Descendants("member")
.Select(e => e.Value)
.ToArray();
This should do the trick:
XDocument xdoc = XDocument.Load(#"Path/to/file");
var result = xdoc.Descendants("member").Select (x => x.Value).ToArray();
Result:
Demo Code
the xml you've provided isn't valid. But assuming you just want the inner text of all member nodes into a string array, I'd just use Linq-To-Xml (XDocument):
var results = XDocument.Parse(xmlString)
.Descendants("member")
.Select(m => m.Value)
.ToArray();
Even though you're using the old XmlDocument API, by throwing in an .OfType<XmlNode>() you can convert an XmlNodeList to a generic enumerable and thereby mix in some linq and lambda syntax, for instance:
var tempArrary = subNode.SelectNodes("member").OfType<XmlNode>().Select(n => n.InnerText).ToArray();

Needing C# LINQ Help reading XML

I've got xml that looks like what I have below. I can read the title but am having trouble getting to the url of media:content. Any suggestions? My non-working c# is below along with the xml.
XNamespace xmlns = "http://www.w3.org/2005/Atom";
var names =
(from data in XDocument.Load("http://channel9.msdn.com/Events/Build/2012/rss").Descendants("item")
let xElement = data.Element("title")
let xElementUrls = data.Element("media")
where xElement != null
select new
{
Title = xElement.Value,
Urls = data.Elements(xmlns + "media:group")
//MediaGroup = data.Element("media:group")
}).ToList();
and the XML:
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:c9="http://channel9.msdn.com">
<channel>
<item>
<title>Building Windows 8 LOB Apps (Repeat)</title>
<media:group>
<media:content url="http://video.ch9.ms/sessions/build/2012/2-104R.mp4"
expression="full" duration="0" fileSize="1" type="video/mp4" medium="video"/>
<media:content url="http://video.ch9.ms/sessions/build/2012/2-104R.wmv"
expression="full" duration="0" fileSize="1" type="video/x-ms-wmv" medium="video"/>
</media:group>
</item>
<item>
<item>
...
</item>
Added this based on L.B.'s suggestion but I can't figure out how to get url's out (it is now returning a list of URL's per item as expected.
var items = xDoc.Descendants("item")
.Where(g => g.Element(media + "group") != null)
.Select(g => new {
Title = g.Element("title").Value,
Url = g.Element(media + "group")
.Element(media + "content")
.Attribute("url").Value
})
.ToList();
var xDoc = XDocument.Load("http://channel9.msdn.com/Events/Build/2012/rss");
XNamespace media = "http://search.yahoo.com/mrss/";
var items = xDoc.Descendants("item")
.Where(g => g.Element(media + "group") != null)
.Select(g => new {
Title = g.Element("title").Value,
Url = g.Element(media + "group")
.Element(media + "content")
.Attribute("url").Value
})
.ToList();
media is a namespace alias, not an element.
You need to get the group element within the http://search.yahoo.com/mrss/ namespace:
XNamespace m = "http://search.yahoo.com/mrss/";
let xElementUrls = data.Element(m + "group")
You have the wrong namespace...
XNamespace xmlns = "http://www.w3.org/2005/Atom";
should be
XNamespace xmlns = "http://search.yahoo.com/mrss/";
And you are combining the namespace and element name incorrectly
...
Urls = data.Elements(xmlns + "group")
....

C# Querying an XML Document

Good Day,
I am trying to query an XML document and have the following query:
XElement root = XElement.Load(#"..\..\Data.xml");
var entries = root.Descendants()
.Where(x => x.Name.LocalName == "Entry")
.ToList();
Console.WriteLine("There are {0} nodes...", entries.Count());
foreach (XElement v in entries)
{
Console.WriteLine(v.Value);
}
and this code works because it pulls the correct number of Entry nodes. The Entry
nodes look like:
<?xml version="1.0" encoding="UTF-8"?>
<Database xmlns="http://www.someurl.org/schemas">
<InfoFromRecord>
<BaseData>
<Entry>
<Date>2006-03-08</Date>XD
<Time>09:20:00</Time>
<EnteredBy>DNS</EnteredBy>
<TextEntry>Record 1</TextEntry>
</Entry>
<Entry>
<Date>2006-03-08</Date>
<Time>09:33:00</Time>
<EnteredBy>MW</EnteredBy>
<TextEntry>Record 2</TextEntry>
</Entry>
<Entry>
<Date>2006-03-08</Date>
<Time>08:58:00</Time>
<EnteredBy>BH</EnteredBy>
<TextEntry>Record 3</TextEntry>
</Entry>
</BaseData>
</InfoFromRecord>
</Database>
The problem is, I want to extract only the Date and Time, not all four fields.
Let's assume your entire XML file looks like this for a clear example:
<Entries>
<Entry>
<Date>2006-03-08</Date>
<Time>09:33:00</Time>
<EnteredBy>XX</EnteredBy>
<TextEntry>Test Data</TextEntry>
</Entry>
</Entries>
You could then do something like this:
var document = XDocument.Load(#"..\..\Data.xml");
var dateAndTimes =
from d in document.Root.Descendants("Entry")
select new
{
Date = d.Element("Date").Value,
Time = d.Element("Time").Value
};
From there, the dateAndTimes type will select an anonymous type of the Date and Time. You can change the anonymous type to be your own type, or something else.
EDIT: The problem is your xmlns. Change your code like so:
XNamespace namespc = "http://www.someurl.org/schemas";
var document = XDocument.Parse(xml);
var dateAndTimes =
from d in document.Root.Descendants(namespc + "Entry")
select new
{
Date = d.Element(namespc + "Date").Value,
Time = d.Element(namespc + "Time").Value
};
I haven't had a chance to try it but something like the following may give you what you are looking for
var entries = from i in root.Descendants()
where Name=='entry'
let date = i.Element('Date').Value
let time = i.ELement('Time').Value
select new Tuple<string,string>(date,time);
foreach (XElement v in entries)
{
Console.WriteLine(v.Element("Date").Value);
Console.WriteLine(v.Element("Time").Value);
}
Do not forget that Descendants finds children at any level, i.e. children, grand-children, etc where Elements find only direct child. So i guess Elements is the safe option in most of the cases.
EDIT : After seeing the XML
You need to include the Namspace also when getting the data
XNamespace ns = "http://www.someurl.org/schemas";
var entries = elm.Descendants().Where(x => x.Name.LocalName == "Entry").ToList();
foreach (XElement v in entries)
{
Console.WriteLine(v.Element(ns+"Date").Value);
Console.WriteLine(v.Element(ns+"Time").Value);
}
IEnumerable<XElement> de = from el in xdoc.Descendants() select el;
foreach (XElement el in de)
{
if (string.Equals(el.Name.ToString(), "movie",
`StringComparison.InvariantCultureIgnoreCase))`enter code here`
StringComparison.InvariantCultureIgnoreCase))
{
date(el);
}

Categories