Get child elements of XML with XmlTextReader - c#

I have following XML:
<UpsHistory>
<UpsSettings>
<Filename>modbusevent.xml</Filename>
<FileDate>04.02.1970</FileDate>
<FileTime>00:05:39</FileTime>
<Type>ENERTRONIC I 3-3 20kVA</Type>
<Location></Location>
<Phases>3</Phases>
<UpsContact>
<Company></Company>
<Department></Department>
<Contact></Contact>
<City></City>
<Street></Street>
<Phone></Phone>
</UpsContact>
</UpsSettings>
<UpsData id="1">
<Date>09.08.2012</Date>
<Time>12:05:53.52</Time>
<EventCode>574</EventCode>
<EventState>A</EventState>
<EventText><![CDATA[IGBT - DRIVERBOARD FAILURE]]></EventText>
<EventAction>/upsexe.cgi?cmd=2003&p1=574&reload=/mbevents.cgi&wait=5</EventAction>
</UpsData>
<UpsData id="2">
<Date>09.08.2012</Date>
<Time>11:23:08.88</Time>
<EventCode>606</EventCode>
<EventState>E</EventState>
<EventText><![CDATA[BYPASS VOLTAGE FAILURE]]></EventText>
<EventAction>/upsexe.cgi?cmd=2003&p1=606&reload=/mbevents.cgi&wait=5</EventAction>
</UpsData>
<UpsData id="3">
<Date>09.08.2012</Date>
<Time>11:23:07.06</Time>
<EventCode>1000</EventCode>
<EventState>E</EventState>
<EventText><![CDATA[CUSTOMER RELAY 1 ON]]></EventText>
<EventAction>/upsexe.cgi?cmd=2003&p1=1000&reload=/mbevents.cgi&wait=5</EventAction>
</UpsData>
<UpsData id="4">
<Date>09.08.2012</Date>
<Time>11:23:06.97</Time>
<EventCode>1003</EventCode>
<EventState>E</EventState>
<EventText><![CDATA[CUSTOMER RELAY 2 OFF]]></EventText>
<EventAction>/upsexe.cgi?cmd=2003&p1=1003&reload=/mbevents.cgi&wait=5</EventAction>
</UpsData>
...
<UpsData id="602">
<Date>08.09.2012</Date>
<Time>11:06:13.84</Time>
<EventCode>606</EventCode>
<EventState>E</EventState>
<EventText><![CDATA[BYPASS VOLTAGE FAILURE]]></EventText>
<EventAction>/upsexe.cgi?cmd=2003&p1=606&reload=/mbevents.cgi&wait=5</EventAction>
</UpsData>
</UpsHistory>
I want to get all UpsData element with child element values, but I only UpsData element id:
Stream sw = CopyAndClose(response.GetResponseStream());
XmlTextReader rdr = new XmlTextReader(sw);
while (rdr.Read())
{
if (rdr.IsStartElement())
{
if (rdr.NodeType == XmlNodeType.Element)
{
if (rdr.Name == "UpsData")
{
rdr.MoveToAttribute("id");
if (rdr.Name == "Date")
{
ConsoleInfo(rdr.Value);
}
}
}
}
}
How I can get child elements values? Thanks!

If you can use XmlDocument or XmlPathNagivator, consider an XPath. For example:
using System.Xml;
...
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
foreach (XmlNode xmlNode in
xmlDocument.DocumentElement.SelectNodes("UpsData/#id[/*]"))
{
// Do something, for example:
Console.Out.WriteLine("Value: " + xmlNode.Value);
}
The XPath "UpsData/#id[/*]" says look for child nodes of called "UpsData" and an "id" attribute that have children and return the "id" attribute.

Related

How can I display XML data using C#

I am trying to display the id attribute of the channel element called id, the inner text of the display-name tag and the inner text of the icon that sometimes is contained inside the channel element.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<tv generator-info-name="xmltv.co.uk" source-info-name="xmltv.co.uk">
<channel id="0052a71acac348ff93f5680aa9c125eb">
<display-name>2910</display-name>
</channel>
<channel id="00da025711e82cf319cb488d5988c099">
<display-name>Sony Movies</display-name>
</channel>
<channel id="00dfea977320f17bb419abaa1f079f39">
<display-name>Good Food</display-name>
<icon src="/images/channels/00dfea977320f17bb419abaa1f079f39.png"/>
</channel>
<channel id="018202232e044b504f9dc5263617d496">
<display-name>The Box</display-name>
<icon src="/images/channels/018202232e044b504f9dc5263617d496.png"/>
</channel>
I tried using this code C# code below But the second if give me a error about not referenced to an object.
XmlDocument doc = new XmlDocument();
doc.Load(xmlLocation);
//dispaly the nodes
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
{
//get the channel
if (node.Name.Equals("channel"))
{
Debug.WriteLine("Channel Name : " + node.ChildNodes[0].Name.ToString()); //or loop through its children as well
//Debug.WriteLine("Channel Name : " + node.AttributeCount.ToString()); //or loop through its children as well
//get the icon element
if(node.ChildNodes[1].Name != null)
Debug.WriteLine("Channel Name : " + node.ChildNodes[1].Name.ToString());
}
}
Although XDocument/XElement and LinQ to XML is the new trend,
to follow your implementation, and adding to it only one feature (using XPATH to query document contents);
Please find the code to fetch channel names and their respective icon source URL's (if exist)
By applying SelectNodes and SelectSingleNode, the API is iterating over the nodes for us.
// Select all the XML elements whose name is "channel"
foreach (XmlNode channelNode in doc.DocumentElement.SelectNodes("channel"))
{
// check if a child element with the name "display-name" exists
XmlNode displayNameNode = channelNode.SelectSingleNode("display-name");
if (displayNameNode != null)
{
// If yes, print the inner text
Debug.WriteLine("Channel Name : " + displayNameNode.InnerText);
}
// then check if the icon node exists
XmlNode iconNode = channelNode.SelectSingleNode("icon");
if (iconNode != null)
{
// and check if it has an attribute with the name "src"
if (iconNode.Attributes["src"] != null)
{
// and if yes, print out its value
Debug.WriteLine(" Icon Src : " + iconNode.Attributes["src"].Value);
}
}
}
First, you need to convert string to XML and load them up in XmlDocument and then use the XPath as shown below. The simple program you can run that in dotnetfiddle.net to check this out.
using System;
using System.Xml;
public class Program
{
public static void Main()
{
string xmlString = "<tv generator-info-name='xmltv.co.uk' source-info-name='xmltv.co.uk'> <channel id='0052a71acac348ff93f5680aa9c125eb'> <display-name>2910</display-name> </channel> <channel id='00da025711e82cf319cb488d5988c099'> <display-name>Sony Movies</display-name> </channel> <channel id='00dfea977320f17bb419abaa1f079f39'> <display-name>Good Food</display-name> <icon src='/images/channels/00dfea977320f17bb419abaa1f079f39.png'/> </channel> <channel id='018202232e044b504f9dc5263617d496'> <display-name>The Box</display-name> <icon src='/images/channels/018202232e044b504f9dc5263617d496.png'/> </channel></tv>";
XmlDocument xmltest = new XmlDocument();
xmltest.LoadXml(xmlString);
XmlNodeList itemNodes = xmltest.SelectNodes("//tv/channel");
foreach(XmlNode itemNode in itemNodes)
{
if (itemNode!= null) {
Console.WriteLine(string.Format("Id:{0}", (itemNode as XmlElement).GetAttribute("id")));
}
}
}
}

xmlNode not deleting

im unable to delete an xml node from a xml file. Im unable to figure out what is the issue in my code. I have attached my code
class Program
{
static void Main(string[] args)
{
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
//try 1
XmlNode firstNode=xDoc.SelectSingleNode("Apartments/Family[Father='Father1']");
xDoc.LastChild.RemoveChild(firstNode);
xDoc.RemoveAll();
//Try2
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// firstNode.ParentNode.RemoveChild(firstNode);
}
}
the Xml document format is
<?xml version="1.0"?>
<Apartments>
<Family>
<Father>Father1</Father>
<Mother>Mother1</Mother>
<Daughter>Daughter1</Daughter>
<Son>Son1</Son>
</Family>
<Family>
<Father>Father2</Father>
<Mother>Mother2</Mother>
<Daughter>Daughter2</Daughter>
<Son>Son2</Son>
</Family>
<Family>
<Father>Father3</Father>
<Mother>Mother3</Mother>
<Daughter>Daughter3</Daughter>
<Son>Son3</Son>
</Family>
<Family>
<Father>Father4</Father>
<Mother>Mother4</Mother>
<Daughter>Daughter4</Daughter>
<Son>Son4</Son>
</Family>
</Apartments>
Please let me know where im wrong.
After the modifications you need to save the changes to file.
XmlDocument xDoc=new XmlDocument();
xDoc.Load(#"C:\Users\MyUser\Desktop\Family.xml");
XmlNodeList nodeColl = xDoc.GetElementsByTagName("Apartments/Family");
foreach (XmlNode xNode in nodeColl)
{
if (xNode["Father"].InnerText == "Father1")
{
xNode.ParentNode.RemoveChild(xNode);
}
}
// save the changes back to file
xDoc.Save(#"C:\Users\MyUser\Desktop\Family.xml");

How to load properties from XML file with C#

I've a method which create an XML file
public void saveXmlButtons()
{
XElement buttons = new XElement("Buttons"); // Create a root node
for (int i = 0; i < 7; i++)
{
XElement id = new XElement("Button", listButtons[i].id.ToString());
XElement type = new XElement("appType", listButtons[i].type);
XElement isActive = new XElement("isActive", listButtons[i].isActive);
XElement name = new XElement("name", listButtons[i].lblName.Content);
XElement pathIcon = new XElement("pathIcon", listButtons[i].pathIcon);
XElement pathApp = new XElement("pathApp", listButtons[i].pathApp);
XElement button = new XElement("Button");
button.Add(id);
button.Add(type);
button.Add(isActive);
button.Add(name);
button.Add(pathIcon);
button.Add(pathApp);
buttons.Add(button);
}
buttons.Save(#"btemp");
loadXmlButton();
}
Output :
<?xml version="1.0" encoding="utf-8"?>
<Buttons>
<Button>
<Button>0</Button>
<appType>None</appType>
<isActive>false</isActive>
<name />
<pathIcon>Resources/add.png</pathIcon>
<pathApp />
</Button>
<Button>
<Button>1</Button>
<appType>None</appType>
<isActive>false</isActive>
<name />
<pathIcon>Resources/add.png</pathIcon>
<pathApp />
</Button>
etc...
</Buttons>
I'm trying to read the different property of each node (Button, appType, isActile), and the documentation doesn't help me..
What is the best way to load each property ? This code doesn't works..
public void loadXmlButton()
{
XmlDocument doc = new XmlDocument();
doc.Load("btemp");
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
{
string s = node.Attributes["pathApp"]?.InnerText;
Console.WriteLine(s);
}
}
As suggested, you'd be far better off using the same LINQ to XML API to read your XML as you did to write it. In addition, pathApp is an element, not an attribute, so you're currently using the old API incorrectly.
Try something like this:
var doc = XDocument.Load("btemp");
foreach (var button in doc.Root.Elements())
{
var id = (int)button.Element("Button");
var type = (string)button.Element("appType");
var isActive = (bool)button.Element("isActive");
...
}

how to read & write xml file in C# not rely on the tag name?

Thank you very much for reading my question.
the bottom is the sample of my xml file.please refer that.
i did some xml files before, but by "CMarkXml". "IntoElement, OutofElement", is very clear.
but when C#...i was lost..
1: how to read & write my xml file without using the tag name. i see some articles about operation on xml file by c#, but all assumed that known the tag name.
2: if without tag name, it is very difficult or not recommend. then how to read & write my xml file by XmlDocument? (sorry, but no Ling please, i am very faint with that...).
3: my idear is, for the xml file, get out some section, we still could parse the section by xmldocument.
4: for the write/modify the xml file, of course, should contain delete some section, delete some "leaf", change the attributes...
Thank you very much for reading the long question, and any help i will very appreciate. If you have a good sample code but not continent paste them here, could you send it to "erlvde#gmail.com"?
<root>
<a>i belong to a</a>
<b>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
<bb>
....(other <bb>)
</b>
</root>
Read your xml into XmlDocument:
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("XML HERE");
Access child nodes:
xmlDocument.ChildNodes[1]
But it's also true that it's very error prone
You can also check if you have child nodes at all:
xmlDocument.HasChildNodes
And get number of child nodes:
xmlDocument.ChildNodes.Count
It looks to me like your elements names contain identifiers. If that is the case, and you have control over the XML schema, I would highly recommend changing your XML to contain elements and/or attributes indicating your identifiers and then use the built in XmlSerializer class for serializing to and from XML. It has many modifiers available, such as XmlElement and XmlAttribute among many others, for formatting the output.
Here is a tutorial to get you started.
If possible, change your XML to something like following which would make it far simpler to manipulate...again if changing the schema is a possibility.
<root>
<a>i belong to a</a>
<b>
<bb id="1">
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb id="2">
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
<bb>
</b>
</root>
Edit this edit reflects the changes you made to your XML
Here is a simple console application which will serialize an object to an XML file and then rehydrate it.
Expected XML
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<a>i belong to a</a>
<b>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
</b>
</root>
Simple Console Application Demonstration
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var items = new root
{
a = "i belong to a",
b = new List<bb>
{
new bb
{
bbClassProperty = new List<int>
{
1,
2,
3,
4,
5
}
},
new bb
{
bbClassProperty= new List<int>
{
1,
2,
3,
4,
5
}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(root));
using (var textWriter = new StreamWriter(#"C:\root.xml"))
{
serializer.Serialize(textWriter, items);
textWriter.Close();
}
using (var stream = new StreamReader(#"C:\root.xml"))
{
var yourObject = serializer.Deserialize(stream);
}
Console.Read();
}
}
#region [Classes]
public class root
{
public string a { get; set; }
public List<bb> b { get; set; }
}
public class bb
{
[XmlElement("bb")]
public List<int> bbClassProperty { get; set; }
}
#endregion
}
Look into the ChildNodes (and similar) properties and methods on your XmlElement object. These will let you iterate over the children of a node and you can then ask that node for its name.
If you have a XmlNode object, you can use XMLNode.FirstChild to get the child, if it has any. You can also use XMLNode.NextSibling to get the next Node of the same parent node.
Why can't you use the names of the nodes? It's the easiest and most common way. Especially if you use XPath or similar.
XPath is also the answer to your second question.
U can use the class XML reader, a simple example is given here.
using System;
using System.Xml;
class Program
{
static void Main()
{
// Create an XML reader for this file.
using (XmlReader reader = XmlReader.Create("perls.xml"))
{
while (reader.Read())
{
// Only detect start elements.
if (reader.IsStartElement())
{
// Get element name and switch on it.
switch (reader.Name)
{
case "perls":
// Detect this element.
Console.WriteLine("Start <perls> element.");
break;
case "article":
// Detect this article element.
Console.WriteLine("Start <article> element.");
// Search for the attribute name on this current node.
string attribute = reader["name"];
if (attribute != null)
{
Console.WriteLine(" Has attribute name: " + attribute);
}
// Next read will contain text.
if (reader.Read())
{
Console.WriteLine(" Text node: " + reader.Value.Trim());
}
break;
}
}
}
}
}
}
The input file text is:
<?xml version="1.0" encoding="utf-8" ?>
<perls>
<article name="backgroundworker">
Example text.
</article>
<article name="threadpool">
More text.
</article>
<article></article>
<article>Final text.</article>
</perls>
Output
Start element.
Start element.
Has attribute name: backgroundworker
Text node: Example text.
Start element.
Has attribute name: threadpool
Text node: More text.
Start element.
Text node:
Start element.
Text node: Final text.enter code here
You can use the following code to if the file does not contain the headers, in the example above.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
reader = XmlReader.Create(filePath, settings)
Would something like this help?
void Iterate(XmlNode parent) {
//do something with
//parent.Name
//parent.Value
//parent.Attributes
foreach(XmlNode child in parent.ChildNodes) {
Iterate(child);
}
}
XmlDocument document = new XmlDocument();
document.Load(filename);
XmlNode parent = document.DocumentElement;
Iterate(parent);
You could also store it like that (sorry for any syntactical error, didn't run it)
public class Document {
public Element DocumentElement { set; get; }
private void Load(string fileName) {
XmlDocument document = new XmlDocument();
document.Load(fileName);
DocumentElement = new Element(this, null);
DocumentElement.Load(document.DocumentElement);
}
}
public class Element {
public string Name { set; get; }
public string Value { set; get; }
//other attributes
private Document document = null;
private Element parent = null;
public Element Parent { get { return parent; } }
public List<Element> Children { set; get; }
private int order = 0;
public Element(Document document, Element parent) {
Name = "";
Value = "";
Children = new List<LayoutElement>();
this.document = document;
this.parent = parent;
order = parent != null ? parent.Children.Count + 1 : 1;
}
private Element GetSibling(bool left) {
if(parent == null) return null;
int add = left ? -1 : +1;
Element sibling = parent.Children.Find(child => child.order == order + add);
return sibling;
}
public Element GetLeftSibling() {
return GetSibling(true);
}
public Element GetRightSibling() {
return GetSibling(false);
}
public void Load(XmlNode node) {
Name = node.Name;
Value = node.Value;
//other attributes
foreach(XmlNode nodeChild in node.Children) {
Element child = new Element(document, this);
child.Load(nodeChild);
Children.Add(child);
}
}
}
Document document = new Document();
document.Load(fileName);
For changing/deleting right now you could iterate the tree and find elements by name, but since name is not unique, you would affect many elements at once. You could add an unique id in every tag like
<bb id="bb1"/>
Then read it in Load function like
id = ((XmlElement)node).GetAttribute("id");
and use this id to iterate through the tree. Sorry I don't have time right now to provide something more detailed.

Reading non-standard elements in a SyndicationItem with SyndicationFeed

With .net 3.5, there is a SyndicationFeed that will load in a RSS feed and allow you to run LINQ on it.
Here is an example of the RSS that I am loading:
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>Title of RSS feed</title>
<link>http://www.google.com</link>
<description>Details about the feed</description>
<pubDate>Mon, 24 Nov 08 21:44:21 -0500</pubDate>
<language>en</language>
<item>
<title>Article 1</title>
<description><![CDATA[How to use StackOverflow.com]]></description>
<link>http://youtube.com/?v=y6_-cLWwEU0</link>
<media:player url="http://youtube.com/?v=y6_-cLWwEU0" />
<media:thumbnail url="http://img.youtube.com/vi/y6_-cLWwEU0/default.jpg" width="120" height="90" />
<media:title>Jared on StackOverflow</media:title>
<media:category label="Tags">tag1, tag2</media:category>
<media:credit>Jared</media:credit>
<enclosure url="http://youtube.com/v/y6_-cLWwEU0.swf" length="233" type="application/x-shockwave-flash"/>
</item>
</channel>
When I loop through the items, I can get back the title and the link through the public properties of SyndicationItem.
I can't seem to figure out how to get the attributes of the enclosure tag, or the values of the media tags. I tried using
SyndicationItem.ElementExtensions.ReadElementExtensions<string>("player", "http://search.yahoo.com/mrss/")
Any help with either of these?
This should give you an idea on how to do it:
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Xml.Linq;
SyndicationFeed feed = reader.Read();
foreach (var item in feed.Items)
{
foreach (SyndicationElementExtension extension in item.ElementExtensions)
{
XElement ele = extension.GetObject<XElement>();
Console.WriteLine(ele.Value);
}
}
Whether you're retrieving the non-XML contents of extension elements or XElement items, you might want to consider using a generic helper function like:
private static T GetExtensionElementValue<T>(SyndicationItem item, string extensionElementName)
{
return item.ElementExtensions.First(ee => ee.OuterName == extensionElementName).GetObject<T>();
}
Depending on whether the elements are guaranteed to be there or whether you are putting this into a reusable library, you may need to add additional defensive programming.
Here is how I managed to retrieve the enclosure link from a feed using SyndicationFeed.
static void Main(string[] args)
{
var feedUrl = "https://blog.stackoverflow.com/index.php?feed=podcast";
using (var feedReader = XmlReader.Create(feedUrl))
{
var feedContent = SyndicationFeed.Load(feedReader);
if (null == feedContent) return;
foreach (var item in feedContent.Items)
{
Debug.WriteLine("Item Title: " + item.Title.Text);
Debug.WriteLine("Item Links");
foreach (var link in item.Links)
{
Debug.WriteLine("Link Title: " + link.Title);
Debug.WriteLine("URI: " + link.Uri);
Debug.WriteLine("RelationshipType: " + link.RelationshipType);
Debug.WriteLine("MediaType: " + link.MediaType);
Debug.WriteLine("Length: " + link.Length);
}
}
}
}
The output is as follows:
Item Title: Podcast #50
Item Links
Link Title:
URI: https://blog.stackoverflow.com/2009/04/podcast-50/
RelationshipType: alternate
MediaType:
Length: 0
Link Title:
URI: http://itc.conversationsnetwork.org/audio/download/ITC.SO-Episode50-2009.04.21.mp3
RelationshipType: enclosure
MediaType: audio/mpeg
Length: 36580016
You can identify the enclosure link from its relationship type.
You can use a combination of LINQ and XPathNavigator to extract the syndication extensions of a feed item (based on namespace URI of the extension). For item enclosures, you will want to examine the item links collection for links that have a RelationshipType of enclosure.
Example:
HttpWebRequest webRequest = WebRequest.Create("http://www.pwop.com/feed.aspx?show=dotnetrocks&filetype=master") as HttpWebRequest;
using (Stream stream = webRequest.GetResponse().GetResponseStream())
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.IgnoreWhitespace = true;
using(XmlReader reader = XmlReader.Create(stream, settings))
{
SyndicationFeed feed = SyndicationFeed.Load(reader);
foreach(SyndicationItem item in feed.Items)
{
// Get values of syndication extension elements for a given namespace
string extensionNamespaceUri = "http://www.itunes.com/dtds/podcast-1.0.dtd";
SyndicationElementExtension extension = item.ElementExtensions.Where<SyndicationElementExtension>(x => x.OuterNamespace == extensionNamespaceUri).FirstOrDefault();
XPathNavigator dataNavigator = new XPathDocument(extension.GetReader()).CreateNavigator();
XmlNamespaceManager resolver = new XmlNamespaceManager(dataNavigator.NameTable);
resolver.AddNamespace("itunes", extensionNamespaceUri);
XPathNavigator authorNavigator = dataNavigator.SelectSingleNode("itunes:author", resolver);
XPathNavigator subtitleNavigator = dataNavigator.SelectSingleNode("itunes:subtitle", resolver);
XPathNavigator summaryNavigator = dataNavigator.SelectSingleNode("itunes:summary", resolver);
XPathNavigator durationNavigator = dataNavigator.SelectSingleNode("itunes:duration", resolver);
string author = authorNavigator != null ? authorNavigator.Value : String.Empty;
string subtitle = subtitleNavigator != null ? subtitleNavigator.Value : String.Empty;
string summary = summaryNavigator != null ? summaryNavigator.Value : String.Empty;
string duration = durationNavigator != null ? durationNavigator.Value : String.Empty;
// Get attributes of <enclosure> element
foreach (SyndicationLink enclosure in item.Links.Where<SyndicationLink>(x => x.RelationshipType == "enclosure"))
{
Uri url = enclosure.Uri;
long length = enclosure.Length;
string mediaType = enclosure.MediaType;
}
}
}
}
Your missing the namespace. Using LINQPad and your example feed:
string xml = #"
<rss version='2.0' xmlns:media='http://search.yahoo.com/mrss/'>
<channel>
<title>Title of RSS feed</title>
<link>http://www.google.com</link>
<description>Details about the feed</description>
<pubDate>Mon, 24 Nov 08 21:44:21 -0500</pubDate>
<language>en</language>
<item>
<title>Article 1</title>
<description><![CDATA[How to use StackOverflow.com]]></description>
<link>http://youtube.com/?v=y6_-cLWwEU0</link>
<media:player url='http://youtube.com/?v=y6_-cLWwEU0' />
<media:thumbnail url='http://img.youtube.com/vi/y6_-cLWwEU0/default.jpg' width='120' height='90' />
<media:title>Jared on StackOverflow</media:title>
<media:category label='Tags'>tag1, tag2</media:category>
<media:credit>Jared</media:credit>
<enclosure url='http://youtube.com/v/y6_-cLWwEU0.swf' length='233' type='application/x-shockwave-flash'/>
</item>
</channel>
</rss>
";
XElement rss = XElement.Parse( xml );
XNamespace media = "http://search.yahoo.com/mrss/";
var player = rss.Element( "channel" ).Element( "item" ).Element(media + "player").Attribute( "url" );
player.Dump();
result: url="http://youtube.com/?v=y6_-cLWwEU0"
The construct to look at is: Element(media + "player") that tells Linq to use the namespace represented by 'media' as well as the element name 'player'.
Brain damage must be setting in on my part, I thought you were using Linq. Anyway, you need to take the namespace into consideration.
Quote "I can't seem to figure out how to get the attributes of the enclosure tag, or the values of the media tags."
Anything formatted <... ...= > is called an "Attribute"
For getting all URLs attributes...
foreach(var item in feed.Items)
{
List<string> urlList = new List<string>();
foreach(SyndicationElementExtension extension in item.ElementExtensions)
{
XElement ele = extension.GetObject<XElement>();
if( ele.HasAttributes && ele.GetAttribute("url")!=null)
{
urlList.Add(ele.GetAttribute("url"));
}
}
//.... store/use item's urlList
}
For a specific one like media:thumbnail
string thumnailUrl = null;
foreach (SyndicationElementExtension ext in item.ElementExtensions)
{
XmlElement ele = ext.GetObject<XmlElement>();
if (ele.Name == "media:thumbnail" && ele.HasAttributes)
{
thumnailUrl = ele.GetAttribute("url");
}
}

Categories