Reading XML / RSS in .Net using System.Data.DataSet? - c#

I really have not worked much with XML and I would appreciate some help.
I am trying to read an RSS feed from WeatherBug
I found some sample code here:
http://geekswithblogs.net/thibbard/archive/2006/01/13/65764.aspx
Where they are using System.Data.DataSet to read the XML feed.
(They are using VBasic I am using VC#)
Here is a sample of the XML I am trying to read:
http://api.wxbug.net/getLiveCompactWeatherRSS.aspx?ACode=A5333948364&zipcode=80918&unittype=0&OutputType=1
In the code example they get the wind speed as follows:
_wind = DS.Tables("wind-speed").Rows(0).Item("wind-speed_Text")
How do I know what to specify for each of the index values? I think I understand how they determined to specify wind-speed but how did they determine how to specify wind-speed_Text?
I can see the values in my debugger using:
m_ds.Tables["wind-speed"].Rows[0].ItemArray
I can see 3 values. "MPH", "3" and 0.
MPH would be the units. "3" would be the speed. Not sure what 0 is.
And how would I access the value at aws:WebURL?
And I am only seeing 8 tables.But there are more values than that. By poking around with the debugger, I found those URLs in the Weather table along with the values for wind-direction and gust-direction.
I thought I had the whole table thing nailed down but there seems to be no rhyme nor reason to it.
Can anyone put me on the right path? Basically I just need to know how to figure out how to find stuff in the DataTables based on what I am seeing in the XML.
Thanks

Quick and easy:
XDocument doc = XDocument.Load("http://api.wxbug.net/getLiveCompactWeatherRSS.aspx?ACode=A5333948364&zipcode=80918&unittype=0&OutputType=1");
XNamespace ns = "http://www.aws.com/aws";
var webUrl = doc.Element(ns + "weather").Element(ns + "WebURL").Value;
var wind = doc.Element(ns + "weather").Element(ns + "wind-speed").Value;
You can also use LINQ:
XDocument doc = XDocument.Load("http://api.wxbug.net/getLiveCompactWeatherRSS.aspx?ACode=A5333948364&zipcode=80918&unittype=0&OutputType=1");
XNamespace ns = "http://www.aws.com/aws";
var v = from d in doc.Elements(ns + "weather") select new { WebUrl = d.Element(ns + "WebURL").Value, WindSpeed = d.Element(ns + "wind-speed").Value};
foreach (var c in v)
{
Console.WriteLine(c.WebUrl + "--" + c.WindSpeed);
}

Related

parsing SOAP xml with namespaces

I have been trying to parse some info and followed the wonderful advise from http://lakenine.com/reading-xml-with-namespaces-using-linq/ I'm sure this is close, but I'm not getting any results to display. No errors, just no results. Breakpoints and checking variables shows that docx has the proper info, but my for loop gets skipped right over. I have played with multiple variations and only manage to crash the code. I believe the issue is with the XPathSelectElements parameter, but dont know what else to try.
At this stage all I need is the token, but I will need to reuse the code later for returns that may have multiple results. Please advise and thank you in advance:
string sampleXML = String.Concat(
"<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"",
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"",
" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">",
" <soap12:Body>",
" <BeginSessionV2Response xmlns=\"http://ws.jobboard.com/jobs/\">",
" <BeginSessionV2Result>ca5522fb93ef499f8ed010a5f4153af7-446298346-SB-4</BeginSessionV2Result>",
" </BeginSessionV2Response>",
" </soap12:Body>",
" </soap12:Envelope>"
);
XmlReader reader = XmlReader.Create(new StringReader(sampleXML));
System.Xml.XmlNameTable nameTable = reader.NameTable;
System.Xml.XmlNamespaceManager namespaceManager = new System.Xml.XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("soap12", "http://www.w3.org/2001/XMLSchema-instance/");
XElement docx = XElement.Load(reader);
string vbResultz = "start: ";
var sessionKey = from pn
in docx.XPathSelectElements("soap12:Body/BeginSessionV2Response/BeginSessionV2Result", namespaceManager)
select (string)pn;
foreach (string pn in sessionKey)
{
vbResultz += pn;
}
ViewBag.REsultz = vbResultz;
return View();
}
First, soap12 prefix you added have wrong uri. Add namespaces to namespaceManager this way :
namespaceManager.AddNamespace("soap12", "http://www.w3.org/2003/05/soap-envelope");
namespaceManager.AddNamespace("ns", "http://ws.jobboard.com/jobs/");
Then you can use them in XPath expression like this :
......
docx.XPathSelectElements("soap12:Body/ns:BeginSessionV2Response/ns:BeginSessionV2Result", namespaceManager)
......
Notice that <BeginSessionV2Response> has default namespace (xmlns attribute without prefix), hence that element and it's descendant without prefix considered inside default namespace. Therefore, we need to add ns prefix in XPath query expression above.

How to get specific Values from a xml file with same Name in a element?

I don't know how to extract values from this specific XML document, and am looking for some help as I'm not very experienced on xml parsing.
I have to use XDocument.Load to load the file.
Actually i am using
doc = XDocument.Load(uri);
challenge = GetValue(doc, "Challenge");
this works without any problems, but how to get the inner values of the Element Rights ? (multiple "Name")
At the end of the day i need to now
Phone = x
Dial = x
HomeAuto = x
BoxAdmin = x
It’s also possible that some of the entries (Phone,Dial,HomeAuto,BoxAdmin) is missing. This
is dynamic.
Here is my xml File:
<SessionInfo>
<SID>68eba0c8cef752a7</SID>
<Challenge>37a5fe9f</Challenge>
<BlockTime>0</BlockTime>
<Rights>
<Name>Phone</Name>
<Access>2</Access>
<Name>Dial</Name>
<Access>2</Access>
<Name>HomeAuto</Name>
<Access>2</Access>
<Name>BoxAdmin</Name>
<Access>2</Access>
</Rights>
</SessionInfo>
Edit: (Add GetValue method)
public string GetValue(XDocument doc, string name)
{
XElement info = doc.FirstNode as XElement;
return info.Element(name).Value;
}
NB: this solution uses extension methods, so the using directives are important or you won't see the required functions.
using System;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections.Generic;
namespace StackOverflow
{
class Program
{
const string xml = "<SessionInfo><SID>68eba0c8cef752a7</SID><Challenge>37a5fe9f</Challenge><BlockTime>0</BlockTime><Rights><Name>Phone</Name><Access>2</Access><Name>Dial</Name><Access>2</Access><Name>HomeAuto</Name><Access>2</Access><Name>BoxAdmin</Name><Access>2</Access></Rights></SessionInfo>";
static void Main(string[] args)
{
XDocument doc = XDocument.Parse(xml); //loads xml from string above rather than file - just to make it easy for me to knock up this sample for you
string nameOfElementToFind = "Name";
IEnumerable<XElement> matches = doc.XPathSelectElements(string.Format("//*[local-name()='{0}']",nameOfElementToFind));
//at this stage you can reference any value from Matches by Index
Console.WriteLine(matches.Count() > 2 ? "Third name is: " + matches.ElementAt(2).Value : "There less than 3 values");
//or can loop through
foreach (XElement match in matches)
{
Console.WriteLine(match.Value);
//or if you also wanted the related access info (this is a bit loose / assumes the Name will always be followed by the related Value
//Console.WriteLine("{0}: {1}", match.Value, match.XPathSelectElement("./following-sibling::*[1]").Value);
}
Console.WriteLine("Done");
Console.ReadKey();
}
}
}
The important bit here is the line IEnumerable<XElement> matches = doc.XPathSelectElements(string.Format("//*[local-name()=\'{0}\']",nameOfElementToFind));. After the string.format takes place the XPath is //*[local-name()='Name']. This XPath statement says to find all nodes with the name Name. The local-name() function's there because we haven't said what schema's being used, in this instance we want any element called Name, regardless of schema.
XmlNamespaceManager nm = new XmlNamespaceManager(new NameTable());
nm.AddNamespace("eg", "http://Example/Namespace/Replace/With/Your/Docs/Namespace");
IEnumerable<XElement> matches = document.XPathSelectElements("//eg:Name", nm);
The double forward-slash says to search anywhere in the document. To limit it to Rights you could say /eg:SessionInfo/eg:Rights/eg:Name. In case you're unfamiliar with it, XPath's an awesome language / essential if you want to get the most out of working with XML docs. If you have any questions about it please give us a shout, or have a look around online; there are great tutorials out there.

how to find an element value in xml when we have multiple namespaces

I want to get the value of the element rsm:CIIHExchangedDocument/ram:ID
But I have problem with multiple namespaces, and null values (I can not know if requested element exists)
It can be achieved this way:
XElement invoice = XElement.Load(invoiceStream);
XNamespace rsm = invoice.GetNamespaceOfPrefix("rsm");
XNamespace ram = invoice.GetNamespaceOfPrefix("ram");
if ((invoice.Element(rsm + "CIIHExchangedDocument")) != null)
{
if (invoice.Element(rsm + "CIIHExchangedDocument").Element(ram + "ID") != null)
{
string id = invoice.Element(rsm + "CIIHExchangedDocument").Element(ram + "ID").Value;
}
}
but I think using xPath will suit my needs better. I want to do something like this:
invoice.XPathSelectElement("rsm:CIIHExchangedDocument/ram:ID"):
I need to retrieve a lot of elements of different depth in the document, and I have many namespaces.
What is the simplest whay to achive this? Execution speed is also important to me.
I believe what you are looking for is the XPathNavigator class. An example of how to use can be found here XpathNaivigator

Returning Data from XML file with Multiple NameSpaces C#

I am having trouble returning data from a Linq to XML query.
I have the following XML
<sdnList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/sdnList.xsd">
<publshInformation>
<Publish_Date>03/14/2013</Publish_Date>
<Record_Count>5440</Record_Count>
</publshInformation>
</sdnList>
I am trying to get the value of Publish Date using the following
XDocument xDoc = XDocument.Load(fileName);
XNamespace xNS = "http://tempuri.org/sdnList.xsd";
XNamespace xNS1 = "http://www.w3.org/2001/XMLSchema-instance";
string strCurrentDate = xDoc.Element(xNS1 + sdnList").Element("publshInformation").Element("Publish_Date").Value;
This just returns an object expected error.
I know my problem is around the namespaces (and most likely is will be a simple solutions)
Thanks
All the elements in that document are in the http://tempuri.org/sdnList.xsd namespace, so you need something like
xDoc.Element(xNS + "sdnList")
.Element(xNS + "publshInformation")
.Element(xNS + "Publish_Date").Value;
This will work:
XNamespace xNS = "http://tempuri.org/sdnList.xsd";
string strCurrentDate = xDoc.Element(xNS + "publshInformation").Element(xNS + "Publish_Date").Value;

Getting the right node in Linq to XML

Im trying to parse an XML file containing all the uploaded videos on a certain channel. Im attempting to get tbe value of the URL attribute in one of the <media:content> nodes and put it in the ViewerLocation field. However there are several of them. My current code is this:
var videos = from xElem in xml.Descendants(atomNS + "entry")
select new YouTubeVideo()
{
Title = xElem.Element(atomNS + "title").Value,
Description = xElem.Element(atomNS + "content").Value,
DateUploaded = xElem.Element(atomNS + "published").Value,
ThumbnailLocation = xElem.Element(mediaNS + "group").Element(mediaNS + "content").Attribute("url").Value,
ViewerLocation = xElem.Element(mediaNS + "group").Element(mediaNS + "content").Attribute("url").Value
};
It gets me the first node in the XML for entry with the name <media:content> as you would expect. However, the first entry in the XML isn't what I want. I want the second.
Below is the relevant XML.
<!-- I currently get the value held in this node -->
<media:content
url='http://www.youtube.com/v/ZTUVgYoeN_b?f=gdata_standard...'
type='application/x-shockwave-flash' medium='video'
isDefault='true' expression='full' duration='215' yt:format='5'/>
<!-- What i actually want is this one -->
<media:content
url='rtsp://rtsp2.youtube.com/ChoLENy73bIAEQ1kgGDA==/0/0/0/video.3gp'
type='video/3gpp' medium='video'
expression='full' duration='215' yt:format='1'/>
<media:content
url='rtsp://rtsp2.youtube.com/ChoLENy73bIDRQ1kgGDA==/0/0/0/video.3gp'
type='video/3gpp' medium='video'
expression='full' duration='215' yt:format='6'/>
I want the second node because it has a type of 'video/3gpp'. How would I go about selecting that one? My logic would be
if attribute(type == "video/3gpp") get this value.
But i do not know how to express this in Linq.
Thanks,
Danny.
Probably something like;
where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
Edit: I didn't quite know how to expand and explain this one without assuming the OP had no knowledge of Linq. You want to make your original query;
from xElem in xml.Descendants(atomNS + "entry")
where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
select new YouTubeVideo() {
...
}
You can interrogate attributes of a node, just like you can look at the elements of the document. If there are multiple elements with that attribute, you could then (assuming you always want the first you find)..
( from xElem in xml.Descendants(atomNS + "entry")
where xElem.Element(atomNS + "content").Attribute("type").Value == "video/3gpp"
select new YouTubeVideo() {
...
}).First();
I changed the original post, as I believe the node you're querying is the Element(atomNS + "content"), not the top level xElem
Using XPath from this Xml Library (Just because I know how to use it) with associated Get methods:
string videoType = "video/3gpp";
XElement root = XElement.Load(file); // or .Parse(xmlstring)
var videos = root.XPath("//entry")
.Select(xElem => new YouTubeVideo()
{
Title = xElem.Get("title", "title"),
Description = xElem.Get("content", "content"),
DateUploaded = xElem.Get("published", "published"),
ThumbnailLocation = xElem.XGetElement("group/content[#type={0}]/url", "url", videoType),
ViewerLocation = xElem.XGetElement("group/content[#type={0}]/url", "url", videoType)
});
If the video type doesn't change, you can replace the XGetElement's with:
xElem.XGetElement("group/content[#type='video/3gpp']/url", "url")
Its a lot cleaner not having to specify namespaces using the library. There is the Microsoft's XPathSelectElements() and XPathSelectElement() you can look into, but they require you to specify the namespaces and don't have the nice Get methods imo. The caveat is that the library isn't a complete XPath implementation, but it does work with the above.

Categories

Resources