Parse XML Elements with LINQ - c#

I have this xml.
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="el-gr" xmlns="http://www.w3.org/2005/Atom">
<title type="text">name.gr</title>
<updated>2011-07-23</updated>
<link href="link" />
<entry>
<title type="html">Οι επιθέσεις σε σκανδιναβικές χώρες</title>
<summary type="text">Η Νορβηγία, μία από τις σκανδιναβικές χώρες, έζησε μετά από πάρα πολλά χρόνια (2006) τον τρόμο. Δείτε αναλυτικά τις τελευταίες «τυφλές» επιθέσεις τα τελευταία χρόνια:...</summary>
<published>2011-07-23T12:54:00+03:00</published>
<link href="link" />
</entry>
i want to parse some of the elements inside . For that i use the following LINQ code.
var list = from y in xelement.Descendants("entry")
select new Update()
{
Title = y.Element("title").Value,
Pubdate = y.Element("published").Value,
Descr = y.Element("content").Value,
Link = y.Element("link").Attribute("href").Value
};
But it does not work. Can anyone tell me what am i doing wrong?

The nodes are all in the http://www.w3.org/2005/Atom namespace. Therefore you need to prefix the queries with this namespace, otherwise the query tries to find those elements in the empty namespace.
XNamespace atom = "http://www.w3.org/2005/Atom";
var list = from y in xelement.Descendants(atom+"entry")
select new Update()
{
Title = y.Element(atom+"title").Value,
Pubdate = y.Element(atom+"published").Value,
Descr = y.Element(atom+"content").Value,
Link = y.Element(atom+"link").Attribute("href").Value
};

In your XML example, there is missing "feed" endtag and you are using an element "content", but I guess "summary" is correct.

Related

Select an particular node (with colon) from xml file and bind it in model class

I need to read an xml file tag which has colon in it and bind it into model class
My xml file
<?xml version="1.0" encoding="utf-8"?>
<feed xml:base=""
xmlns=""
xmlns:d=""
xmlns:m="">
<id>my url</id>
<title type="text">ItemList</title>
<updated>2019-05-07T14:18:08Z</updated>
<link rel="self" title="ItemList" href="ItemList" />
<entry m:etag="">
<id></id>
<category term="NAV.ItemList" scheme="" />
<link rel="edit" title="ItemList" href="" />
<title />
<updated>2019-05-07T14:18:08Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:No>LSU-458</d:No>
<d:Description>speaker</d:Description>
<d:Type>Inventory</d:Type>
</m:properties>
</content>
</entry>
</feed>
My c# code
List<CustomerModel> customers = new List<CustomerModel>();
doc.Load(Server.MapPath("~/oWtMRUR8_.xml"));
foreach (XmlNode node in
doc.SelectNodes("/feed/id/title/updated/link/mproperties"))
{
customers.Add(new CustomerModel
{
No = int.Parse(node["d:No"].InnerText),
Description = node["d:Description"].InnerText,
Type = node["d:Type"].InnerText
});
}
return View(customers);
I need to bind only the d:no,d:description,d:type in my model class using foreach loop,these tags are with colon so I am not able to extract the contents in the tag and namespace was mentioned as an option(but didn't worked). I am new to this and can't able to find the right method, hope anyone helps.
My expected result:
No =LSU-458 ,
Description = speaker,
Type = Inventory
Firstly, the XML is not valid, the namespace declarations need a name, for example
<feed xml:base="""" xmlns="""" xmlns:d=""d"" xmlns:m=""m"">
Then you can loop through the properties like this:
var root = doc.SelectSingleNode("/feed/entry/content");
foreach (XmlNode node in root.ChildNodes)
{
customers.Add(new CustomerModel
{
No = node["d:No"].InnerText,
Description = node["d:Description"].InnerText,
Type = node["d:Type"].InnerText
});
}
And finally, you cannot int.Parse() the d:No because it's a string.
Hi all I got the answer and I am posting it, hope it might help someone in future:
XmlNamespaceManager namespaces = new
XmlNamespaceManager(doc.NameTable);
namespaces.AddNamespace("m", "our_url_link");
XmlNodeList nodemsg = doc.SelectNodes("//m:properties", namespaces);
foreach (XmlNode xnz in nodemsg)
{
customers.Add(new CustomerModel
{
//item.Element("d:No").Value
No = xnz["d:No"].InnerText,
Description = xnz["d:Description"].InnerText,
Type = xnz["d:Type"].InnerText
});
}

How to get enclosure url with XElement C# Console

I read multiple feed from many sources with C# Console, and i have this code where i load XML From sources:
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
XElement xdoc = XElement.Load(sourceURLX);
How to get enclosure url and show as variable?
If I understand your question correctly (I'm making a big assumption here) - you want to select an attribute from the root (or 'enclosing') tag, named 'url'?
You can make use of XPath queries here. Consider the following XML:
<?xml version="1.0" encoding="utf-8"?>
<root url='google.com'>
<inner />
</root>
You could use the following code to retrieve 'google.com':
String query = "/root[1]/#url";
XmlDocument doc = new XmlDocument();
doc.Load(sourceURLX);
String value = doc.SelectSingleNode(query).InnerText;
Further information about XPath syntax can be found here.
Edit: As you stated in your comment, you are working with the following XML:
<item>
<description>
</description>
<enclosure url="blablabla.com/img.jpg" />
</item>
Therefore, you can retrieve the url using the following XPath query:
/item[1]/enclosure[1]/#url
With xml like below
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>title</title>
<link>https://www.link.com</link>
<description>description</description>
<item>
<title>RSS</title>
<link>https://www.link.com/xml/xml_rss.asp</link>
<description>description</description>
<enclosure url="https://www.link.com/media/test.wmv"
length="10000"
type="video/wmv"/>
</item>
</channel>
</rss>
You will get url by reading attribute
var document = XDocument.Load(sourceURLX);
var url = document.Root
.Element("channel")
.Element("item")
.Element("enclosure")
.Attribute("url")
.Value;
To get multiple urls
var urls = document.Descendants("item")
.Select(item => item.Element("enclosure").Attribute("url").Value)
.ToList();
Using foreach loop
foreach (var item in document.Descendants("item"))
{
var title = item.Element("title").Value;
var link = item.Element("link").Value;
var description = item.Element("description").Value;
var url = item.Element("enclosure").Attribute("url").Value;
// save values to database
}

Reading child nodes from xml string using C#, LINQ

- <entry xml:base="http://testserver.windows.net/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2015-08-30T00%3A04%3A02.9193525Z'"">
<id>http://testserver.windows.net/Players(PartitionKey='zzz',RowKey='000125')</id>
<category term="testServer.Players" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="Players" href="Players(PartitionKey='zzz',RowKey='000125')" />
<title />
<updated>2014-04-30T00:53:42Z</updated>
- <author>
<name />
</author>
- <content type="application/xml">
- <m:properties>
<d:PartitionKey>zzz</d:PartitionKey>
<d:RowKey>000125</d:RowKey>
<d:Timestamp m:type="Edm.DateTime">2014-04-30T00:04:02.9193525Z</d:Timestamp>
<d:Name>Black color</d:Name>
<d:Comments>Test comments</d:Comments>
</m:properties>
</content>
</entry>
How can I read "m:properties" descendants using C# or LINQ.
This xml string is stored in variable of type XElement
You can use combination of XNamespace+"element local name" to reference element in namespace, for example :
XElement myxelement = XElement.Parse("your XML string here");
XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
List<XElement> properties = myxelement.Descendants(m+"properties").ToList();
I think this could show you how to use Linq to XML
read the data from XML Structure using c#
If anything else makes problems, just debug a little, see what you get from L2X operation, and move a step deeper trough data tree.
Using Linq2XML
var xDoc = XDocument.Load(filename);
var dict = xDoc.Descendants("m:properties")
.First()
.Attributes()
.ToDictionary(x => x.Name, x => x.Value);
Setup namespace manager. Note that .net library does not support default namespace, so I added prefix "ns" to default namespace.
use xpath or linq to query xml. Following example uses xpath.
XmlNamespaceManager NamespaceManager = new XmlNamespaceManager(new NameTable());
NamespaceManager.AddNamespace("base", "http://testserver.windows.net/");
NamespaceManager.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
NamespaceManager.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
NamespaceManager.AddNamespace("ns", "http://www.w3.org/2005/Atom"); XDocument doc = XDocument.Parse(XElement);
var properties = doc.XPathSelectElement("/ns:entry/ns:content/m:properties", NamespaceManager);

Read xml descendants collection from xml string [duplicate]

- <entry xml:base="http://testserver.windows.net/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:etag="W/"datetime'2015-08-30T00%3A04%3A02.9193525Z'"">
<id>http://testserver.windows.net/Players(PartitionKey='zzz',RowKey='000125')</id>
<category term="testServer.Players" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" title="Players" href="Players(PartitionKey='zzz',RowKey='000125')" />
<title />
<updated>2014-04-30T00:53:42Z</updated>
- <author>
<name />
</author>
- <content type="application/xml">
- <m:properties>
<d:PartitionKey>zzz</d:PartitionKey>
<d:RowKey>000125</d:RowKey>
<d:Timestamp m:type="Edm.DateTime">2014-04-30T00:04:02.9193525Z</d:Timestamp>
<d:Name>Black color</d:Name>
<d:Comments>Test comments</d:Comments>
</m:properties>
</content>
</entry>
How can I read "m:properties" descendants using C# or LINQ.
This xml string is stored in variable of type XElement
You can use combination of XNamespace+"element local name" to reference element in namespace, for example :
XElement myxelement = XElement.Parse("your XML string here");
XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
List<XElement> properties = myxelement.Descendants(m+"properties").ToList();
I think this could show you how to use Linq to XML
read the data from XML Structure using c#
If anything else makes problems, just debug a little, see what you get from L2X operation, and move a step deeper trough data tree.
Using Linq2XML
var xDoc = XDocument.Load(filename);
var dict = xDoc.Descendants("m:properties")
.First()
.Attributes()
.ToDictionary(x => x.Name, x => x.Value);
Setup namespace manager. Note that .net library does not support default namespace, so I added prefix "ns" to default namespace.
use xpath or linq to query xml. Following example uses xpath.
XmlNamespaceManager NamespaceManager = new XmlNamespaceManager(new NameTable());
NamespaceManager.AddNamespace("base", "http://testserver.windows.net/");
NamespaceManager.AddNamespace("d", "http://schemas.microsoft.com/ado/2007/08/dataservices");
NamespaceManager.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
NamespaceManager.AddNamespace("ns", "http://www.w3.org/2005/Atom"); XDocument doc = XDocument.Parse(XElement);
var properties = doc.XPathSelectElement("/ns:entry/ns:content/m:properties", NamespaceManager);

How to query XElement with two namespaces

I'm trying to find the inner text value of an element using LINQ-to-XML (an XElement object). I make my service call and get an XML response back that I've successfully loaded into an XElement object. I want to extract the inner text of one of the elements - however, every time I try to do this, I get a null result.
I feel like I'm missing something super-simple, but I'm fairly new to LINQ-to-XML. Any help is appreciated.
I'm trying to get the inner text value of the StatusInfo/Status element. Here's my XML document that's returned:
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
<title type="text">My Response</title>
<id>tag:foo.com,2012:/bar/06468dfc-32f7-4650-b765-608f2b852f22</id>
<author>
<name>My Web Services</name>
</author>
<link rel="self" type="application/atom+xml" href="http://myServer/service.svc/myPath" />
<generator uri="http://myServer" version="1">My Web Services</generator>
<entry>
<id>tag:foo.com,2012:/my-web-services</id>
<title type="text" />
<updated>2012-06-27T14:22:42Z</updated>
<category term="tag:foo.com,2008/my/schemas#system" scheme="tag:foo.com,2008/my/schemas#type" />
<content type="application/vnd.my.webservices+xml">
<StatusInfo xmlns="tag:foo.com,2008:/my/data">
<Status>Available</Status> <!-- I want the inner text -->
</StatusInfo>
</content>
</entry>
</feed>
Here's a snippet of code that I'm using to extract the value (which doesn't work):
XElement root = XElement.Load(responseReader);
XNamespace tag = "tag:foo.com,2008:/my/data";
var status = (from s in root.Elements(tag + "Status")
select s).FirstOrDefault();
My status variable is always null. I've tried several variations on this, but to no avail. The part that's confusing me is the namespace -- tag and 2008 are defined. I don't know if I'm handling this correctly or if there's a better way to deal with this.
Also, I don't have control over the XML schema or the structure of the XML. The service I'm using is out of my control.
Thanks for any help!
Try Descendants() instead of Elements():
XElement x = XElement.Load(responseReader);
XNamespace ns = "tag:foo.com,2008:/my/data";
var status = x.Descendants(ns + "Status").FirstOrDefault().Value;
There are 2 Namespaces in the feed:
the Atom namespace
the tag namespace
The outer xml needs to use the Atom namespace, while a portion of the inner xml needs to use the tag namespace. i.e.,
var doc = XDocument.Load(responseReader);
XNamespace nsAtom = "http://www.w3.org/2005/Atom";
XNamespace nsTag = "tag:foo.com,2008:/my/data";
// get all entry nodes / use the atom namespace
var entry = doc.Root.Elements(nsAtom + "entry");
// get all StatusInfo elements / use the atom namespace
var statusInfo = entry.Descendants(nsTag + "StatusInfo");
// get all Status / use the tag namespace
var status = statusInfo.Elements(nsTag + "Status");
// get value of all Status
var values = status.Select(x => x.Value.ToString()).ToList();

Categories

Resources