Read XML using SelectSingleNode - c#

I am using following code to read the specified XML
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\">
<title>Gmail - Inbox for xxxx#gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>1</fullcount>
<link rel=\"alternate\" href=\"https://mail.google.com/mail\" type=\"text/html\" />
<modified>2016-02-07T12:11:21Z</modified>
<entry>
<title>Access for less secure apps has been turned on</title>
<summary>Access for less secure apps has been turned on Hi Buddy, You recently changed your security settings so</summary>
<link rel=\"alternate\" href=\"https://mail.google.com/mail?account_id=agl.testauto#gmail.com&message_id=152bb8ccd28d824b&view=conv&extsrc=atom\" type=\"text/html\" />
<modified>2016-02-07T11:45:12Z</modified>
<issued>2016-02-07T11:45:12Z</issued>
<id>tag:gmail.google.com,2004:1525516088640373323</id>
<author>
<name>Google</name>
<email>no-reply#accounts.google.com</email>
</author>
</entry>
</feed>
Below code is being used and problem is I am not getting values for title element with last line of code.
response = Encoding.UTF8.GetString(objclient.DownloadData("https://mail.google.com/mail/feed/atom"));
response = response.Replace("<feed version*\"0.3\" xmlns=\"http://purl.org/atom/01#\">", "<feed>");
xdoc.LoadXml(response);
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("feed", "http://purl.org/atom/ns#");
node = xdoc.SelectSingleNode("//feed:fullcount", nsmgr);
Variables.emailcount = Convert.ToInt16(node.InnerText);
System.Diagnostics.Debug.Write(Variables.emailcount);
tagline = xdoc.SelectSingleNode("//feed:tagline", nsmgr).InnerText;
node2 = xdoc.SelectSingleNode("//feed:entry", nsmgr);
message_subject = node2.SelectSingleNode("//feed/entry/title", nsmg).InnerText; ---- >>> Issue Line
Just wondering where could be the issue.
Thanks

try
message_subject = node2.SelectSingleNode("//feed:entry/feed:title",
nsmgr).InnerText;
note: you have used "feed" as the name of the namespace, so the title should also be qualified

Make your life easier by using SyndicationFeed defined into System.ServiceModel.Syndication namespace from System.ServiceModel assembly.
SyndicationFeed syndicationFeed = null;
using (var reader = XmlReader.Create("https://mail.google.com/mail/feed/atom"))
{
syndicationFeed = SyndicationFeed.Load(reader);
}
if(syndicationFeed != null)
{
foreach (SyndicationItem item in syndicationFeed.Items)
{
// Do everything you want here by checking properties you need from SyndicationItem item variable.
}
}
To know what are properties that SyndicationItem offer check this link.

I prefer xml linq
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const int NUMBER_OF_XML = 3;
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\">" +
"<title>Gmail - Inbox for xxxx#gmail.com</title>" +
"<tagline>New messages in your Gmail Inbox</tagline>" +
"<fullcount>1</fullcount>" +
"<link rel=\"alternate\" href=\"https://mail.google.com/mail\" type=\"text/html\" />" +
"<modified>2016-02-07T12:11:21Z</modified>" +
"<entry>" +
"<title>Access for less secure apps has been turned on</title>" +
"<summary>Access for less secure apps has been turned on Hi Buddy, You recently changed your security settings so</summary>" +
"<link rel=\"alternate\" href=\"https://mail.google.com/mail?account_id=agl.testauto#gmail.com&message_id=152bb8ccd28d824b&view=conv&extsrc=atom\" type=\"text/html\" />" +
"<modified>2016-02-07T11:45:12Z</modified>" +
"<issued>2016-02-07T11:45:12Z</issued>" +
"<id>tag:gmail.google.com,2004:1525516088640373323</id>" +
"<author>" +
"<name>Google</name>" +
"<email>no-reply#accounts.google.com</email>" +
"</author>" +
"</entry>" +
"</feed>";
XDocument doc = XDocument.Parse(xml);
XElement firstNode = (XElement)doc.FirstNode;
XNamespace ns = firstNode.Name.Namespace;
var results = doc.Elements(ns + "feed").Select(x => new {
tagline = (string)x.Element(ns + "tagline"),
message_subject = (string)x.Element(ns + "entry").Element(ns + "title")
}).FirstOrDefault();
}
}
}

Related

Reading XML file using Linq

I have tried to read XML file using Linq. Here is my code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LinqToXml
{
class Program
{
static void Main(string[] args)
{
XDocument xdoc = XDocument.Load(#"E:\\XML\\test.xml");
xdoc.Descendants("Title").Select(t => new
{
fontType = t.Attribute("fontType").Value,
fontSize = t.Attribute("fontSize").Value,
fontColor = t.Attribute("fontColor").Value,
Underline = t.Attribute("Underline").Value,
Bold = t.Attribute("Bold").Value,
Italic = t.Attribute("Italic").Value,
}).ToList().ForEach(t =>
{
Console.WriteLine("fontType : " + t.fontType);
Console.WriteLine("fontSize : " + t.fontSize);
Console.WriteLine("fontColor : " + t.fontColor);
Console.WriteLine("Underline : " + t.Underline);
Console.WriteLine("Bold : " + t.Bold);
Console.WriteLine("Italic : " + t.Italic);
});
Console.ReadLine();
}
}
}
It gives an below exception
An unhandled exception of type 'System.NullReferenceException'
occurred in programm.exe
But I can't find what is the error. Can anyone help me..
This is the XML file which I have used..
<Styles>
<Title>
<fontType>TimesNewRoman</fontType>
<fontSize>20</fontSize>
<fontColor>black</fontColor>
<Underline>No</Underline>
<Bold>bold</Bold>
<Italic>No</Italic>
</Title>
<Title>
<fontType>TimesNewRoman</fontType>
<fontSize>20</fontSize>
<fontColor>black</fontColor>
<Underline>No</Underline>
<Bold>bold</Bold>
<Italic>italic</Italic>
</Title>
</Styles>
There aren't any fontType, fontSize, etc. attributes on the Title element. fontType, fontSize are elements, so you should use
fontType = t.Element("fontType").Value

Create Protege Readable Ontology from .NET

I am trying to create a protégé readable ontology from .NET.
I started with a 4GB .nt file and parsed out the needed classes and instances that I wish to use. Those are stored in memory since I got it down to less than 1 minute and roughly 1GB. They are in the form of Dictionary<String,HashSet<String>> right now. The next step is to take that data and move it into an OWL Ontology. Is there anywhere to start with how to manually loop through and do this? All of my research points me to using Manchester OWL, but everything I can find is for use with existing tools that don't fit my needs. I am looking for just doing a simple loop probably with LINQ to XML and I am unsure of how to format that or where to look to find how to do this.
Thanks
Jimmy
You can start with this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string definition =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<Ontology xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xsi:schemaLocation=\"http://www.w3.org/2002/07/owl# http://www.w3.org/2009/09/owl2-xml.xsd\"" +
" xmlns=\"http://www.w3.org/2002/07/owl#\"" +
" xml:base=\"http://example.com/myOntology\"" +
" ontologyIRI=\"http://example.com/myOntology\">" +
"</Ontology>";
XDocument doc = XDocument.Parse(definition);
XElement ontology = (XElement)doc.FirstNode;
XNamespace ns = ontology.Name.Namespace;
ontology.Add(new XElement[] {
new XElement(ns + "Prefix", new XAttribute[] {
new XAttribute("name", "myOnt"),
new XAttribute("IRI", "http://example.com/myOntology#")
}),
new XElement(ns + "Import", "http://example.com/someOtherOntology")
});
}
}
}
​

Unable to Parse XMl after unwrapping soap body

I have been trying hard to parse an xml string, but all to no avail
<EnquirySingleItemResponse xmlns="http://tempuri.org/"> <EnquirySingleItemResult>
<Response>
<MSG>SUCCESS</MSG>
<INFO>TESTING</INFO>
</Response> </EnquirySingleItemResult> </EnquirySingleItemResponse>
My Code returns null or the texts in the xml tags no matter how i parse it. I have checked some post, but they seem not to be working.
See my code snipped below
XElement anotherUnwrappedResponse = ( from _xml in axdoc.Descendants(tempuri + "EnquirySingleItemResponse")
select _xml).FirstOrDefault();
string response = anotherUnwrappedResponse.Value;
axdoc.Descendants is used because i unwrapped the soap body, to have the xml above
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input =
"<EnquirySingleItemResponse xmlns=\"http://tempuri.org/\">" +
"<EnquirySingleItemResult>" +
"<Response>" +
"<MSG>SUCCESS</MSG>" +
"<INFO>TESTING</INFO>" +
"</Response> </EnquirySingleItemResult> </EnquirySingleItemResponse>";
XDocument doc = XDocument.Parse(input);
string msg = doc.Descendants().Where(x => x.Name.LocalName == "MSG").FirstOrDefault().Value;
string info = doc.Descendants().Where(x => x.Name.LocalName == "INFO").FirstOrDefault().Value;
}
}
}
​

Reading XML File with multiple NS

I am trying to read an XML feed to get the last post date. My xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>
<channel>
<title>mysite</title>
<atom:link href="http://www.mysite.com/news/feed/" rel="self" type="application/rss+xml" />
<link>http://www.mysite.com/news</link>
<description>mysite</description>
<lastBuildDate>Tue, 22 Nov 2011 16:10:27 +0000</lastBuildDate>
<language>en</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>http://wordpress.org/?v=3.0.4</generator>
<item>
<title>My first post!</title>
<link>http://www.mysite.com/news/2011/11/22/docstore-v2-released/</link>
<comments>http://www.mysite.com/news/2011/11/22/docstore-v2-released/#comments</comments>
<pubDate>Tue, 22 Nov 2011 16:10:27 +0000</pubDate>
<dc:creator>mysite</dc:creator>
<category><![CDATA[News]]></category>
<category><![CDATA[Promotions]]></category>
<category><![CDATA[docstore]]></category>
I didn't show all of the xml since it is rather long.
My method, so far, looks like this:
private void button1_Click(object sender, EventArgs e)
{
var XmlDoc = new XmlDocument();
// setup the XML namespace manager
var mgr = new XmlNamespaceManager(XmlDoc.NameTable);
// add the relevant namespaces to the XML namespace manager
mgr.AddNamespace("ns", "http://purl.org/rss/1.0/modules/content/");
var webClient = new WebClient();
var stream = new MemoryStream(webClient.DownloadData("http://www.mysite.com/news/feed/"));
XmlDoc.Load(stream);
// **USE** the XML anemspace in your XPath !!
XmlElement NodePath = (XmlElement)XmlDoc.SelectSingleNode("/ns:Response");
while (NodePath != null)
{
foreach (XmlNode Xml_Node in NodePath)
{
Console.WriteLine(Xml_Node.Name + ": " + Xml_Node.InnerText);
}
}
}
I'm having a problem with it telling me:
Namespace Manager or XsltContext needed. This query has a prefix,
variable, or user-defined function.
All I want to pull out of this xml code is the 'lastBuildDate'. I'm going in circles trying to get this code right.
Can someone tell me what I am doing wrong here?
Thank you!
You're not using the namespace manager.
// **USE** the XML anemspace in your XPath !!
XmlElement NodePath = (XmlElement)XmlDoc.SelectSingleNode("/ns:Response", mgr);
There is only one of the element you are going after, you could go directly to it using the XPath. That element is also in the default namespace, so you do not need to do anything special to get to it. What about:
var XPATH_BUILD_DATE="/rss/channel/lastBuildDate";
private void button1_Click(object sender, EventArgs e){
var xmlDoc = new XmlDocument();
var webClient = new WebClient();
var stream = new MemoryStream(webClient.DownloadData("http://www.mysite.com/news/feed/"));
xmlDoc.Load(stream);
XmlElement xmlNode = (XmlElement)xmlDoc.SelectSingleNode(XPATH_BUILD_DATE);
Console.WriteLine(xmlNode.Name + ": " + xmlNode.InnerText);
}
If you did however need to dig into elements in a different namespace, you can do that also with the XPath (example, getting the dc:creator:
/rss/channel/item[1]/*[local-name() = 'creator']

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