I have a response XML in which I am trying to find the id of Entry tag, but any combination is yielding null always.
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<status feed="http://feeds.bbci.co.uk/news/rss.xml?edition=int" xmlns="http://superfeedr.com/xmpp-pubsub-ext">
<http code="200">Fetched (ring) 200 242 and parsed 2/42 entries</http>
<next_fetch>1970-01-18T20:24:54.289Z</next_fetch>
<entries_count_since_last_maintenance>35</entries_count_since_last_maintenance>
<velocity>65.3</velocity>
<popularity>3.713318235496007</popularity>
<generated_ids>true</generated_ids>
<title>BBC News - Home</title>
<period>242</period>
<last_fetch>1970-01-18T20:24:54.045Z</last_fetch>
<last_parse>1970-01-18T20:24:54.045Z</last_parse>
<last_maintenance_at>1970-01-18T20:24:07.350Z</last_maintenance_at>
</status>
<link title="BBC News - Home" rel="alternate" href="https://www.bbc.co.uk/news/" type="text/html"/>
<link title="BBC News - Home" rel="image" href="https://news.bbcimg.co.uk/nol/shared/img/bbc_news_120x60.gif" type="image/gif"/>
<title>BBC News - Home</title>
<updated>2018-11-15T14:59:15.000Z</updated>
<id>bbc-news-home-2018-11-15-14</id>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.georss.org/georss" xmlns:as="http://activitystrea.ms/spec/1.0/" xmlns:sf="http://superfeedr.com/xmpp-pubsub-ext" xml:lang="en">
<id>https://www.bbc.co.uk/news/world-us-canada-46225486</id>
<published>2018-11-15T14:44:37.000Z</published>
<updated>2018-11-15T14:44:37.000Z</updated>
<title>Trump attacks Mueller's Russia inquiry as 'absolutely nuts'</title>
<summary type="text">The US president says the Russia inquiry is a "total mess" and calls investigators "a disgrace".</summary>
<link title="Trump attacks Mueller's Russia inquiry as 'absolutely nuts'" rel="alternate" href="https://www.bbc.co.uk/news/world-us-canada-46225486" type="text/html" xml:lang="en"/>
<link title="Trump attacks Mueller's Russia inquiry as 'absolutely nuts'" rel="thumbnail" href="http://c.files.bbci.co.uk/E64B/production/_104355985_gettyimages-1060191940.jpg" type="image/jpeg" xml:lang="en"/>
</entry>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.georss.org/georss" xmlns:as="http://activitystrea.ms/spec/1.0/" xmlns:sf="http://superfeedr.com/xmpp-pubsub-ext" xml:lang="en">
<id>https://www.bbc.co.uk/news/world-africa-46221238</id>
<published>2018-11-15T14:35:47.000Z</published>
<updated>2018-11-15T14:35:47.000Z</updated>
<title>Ethiopia arrests former deputy spy chief Yared Zerihun</title>
<summary type="text">Prime Minister Abiy Ahmed promised to combat corruption and rights abuses when he took office.</summary>
<link title="Ethiopia arrests former deputy spy chief Yared Zerihun" rel="alternate" href="https://www.bbc.co.uk/news/world-africa-46221238" type="text/html" xml:lang="en"/>
<link title="Ethiopia arrests former deputy spy chief Yared Zerihun" rel="thumbnail" href="http://c.files.bbci.co.uk/52E9/production/_104352212_872d41ed-8ac9-4b7b-abfc-b4d898a71670.jpg" type="image/jpeg" xml:lang="en"/>
</entry>
</feed>
to fetch the id these are the combination I tried
"/feed/entry/id/text()"
"entry/id/text()"
`doc.GetElementsByTagName("entry").SelectNodes("id/text()")I
i can go to id by iteration with childNodes but what will be XPath for that.
but if I try "/*" on the whole document it gives me one node count. why ?
The xml elements in the xml are declared within the http://www.w3.org/2005/Atom xml namespace.
This namespace has to be considered in the XPATHstatement.
You have to register this namespace with an XmlNamespaceManager and apply the chosen prefix (here:x) in the XPATHstatement as: //x:feed/x:entry/x:id.
XmlDocument doc = new XmlDocument();
String pathToYourXmlFile = #"c:\folder\file.xml";
doc.Load(pathToYourXmlFile);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://www.w3.org/2005/Atom");
XmlNodeList ids = doc.SelectNodes("//x:feed/x:entry/x:id", nsmgr);
foreach (XmlNode id in ids)
{
Console.WriteLine(id.InnerText);
}
You xml contains namespace xmlns="http://www.w3.org/2005/Atom" at root level node <feed>
And you are using /feed/entry/id/text() these kind of XPath but these path are not suitable for this xml and that's why you can't get any desired value.
You need to use below XPath to get id's of all <entry> node.
var ids = doc.SelectNodes("//*[name()='feed']/*[name()='entry']/*[name()='id']/text()");
Here i created a sample console app for demonstration purpose.
class program
{
public static void Main()
{
XmlDocument doc = new XmlDocument();
doc.Load(#"Path to your xml file");
var ids = doc.SelectNodes("//*[name()='feed']/*[name()='entry']/*[name()='id']/text()");
foreach (XmlNode id in ids)
{
Console.WriteLine(id.Value);
}
Console.ReadLine();
}
}
Output:
Related
- <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);
- <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);
I am using c# to read (attempting to) an RSS feed, but I am getting an error "Namespace prefix 'cb' is not defined" , I am pretty new to XML and C# and was hoping for some help, I read a bit on creating the Namespace but I am not 100% sure I am grasping it.
Any help would be greatly appreciated.
The C# code is:
/*
Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
*/
// Create an XmlNamespaceManager to resolve the default namespace.
XmlDocument xm = new XmlDocument();
xm.Load(Variables.USFeed.ToString());
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xm.NameTable);
nsmgr.AddNamespace("rdf", "http://purl.org/rss/1.0/");
XmlNodeList xnode = xm.GetElementsByTagName("item");
foreach (XmlNode xmn in xnode)
{
XmlElement currencyElement = (XmlElement)xmn;
if (currencyElement.HasAttribute("rdf:about"))
{
Output0Buffer.AddRow();
Output0Buffer.observationPeriod = currencyElement.SelectSingleNode("cb:statistics/cb:exchangeRate/cb:observationPeriod", nsmgr).InnerText;
Output0Buffer.targetCurrency = currencyElement.SelectSingleNode("cb:statistics/cb:exchangeRate/cb:targetCurrency", nsmgr).InnerText;
Output0Buffer.baseCurrency = currencyElement.SelectSingleNode("cb:statistics/cb:exchangeRate/cb:baseCurrency", nsmgr).InnerText;
Output0Buffer.exchangeRate = double.Parse(currencyElement.SelectSingleNode("cb:statistics/cb:exchangeRate/cb:value", nsmgr).InnerText);
}
}
and the summarized version of the rss is:
<?xml version="1.0" encoding="ISO-8859-1"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3c.org/1999/02/22-rdf-syntax-ns#rdf.xsd">
<channel rdf:about="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_ALL.xml">
<title xml:lang="en">Bank of Canada: Noon Foreign Exchange Rates</title>
<link>http://www.bankofcanada.ca/rates/exchange/noon-rates-5-day/</link>
<description>Current day's noon foreign exchange rates from the Bank of Canada. Published at about 12:15 ET.</description>
<items>
<rdf:Seq>
<rdf:li rdf:resource="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_USD.xml" />
<rdf:li rdf:resource="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_VEF.xml" />
<rdf:li rdf:resource="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_VND.xml" />
</rdf:Seq>
</items>
</channel>
<item rdf:about="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_USD.xml">
<title xml:lang="en">CA: 0.9382 USD = 1 CAD 2014-01-06 Bank of Canada noon rate</title>
<cb:statistics>
<cb:country>CA</cb:country>
<cb:exchangeRate>
<cb:value decimals="4">0.9382</cb:value>
<cb:baseCurrency>CAD</cb:baseCurrency>
<cb:targetCurrency>USD</cb:targetCurrency>
<cb:rateType>Bank of Canada noon rate</cb:rateType>
<cb:observationPeriod frequency="daily">2014-01-06T12:15:00-05:00</cb:observationPeriod>
</cb:exchangeRate>
</cb:statistics>
</item>
<item rdf:about="http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_ARS.xml">
<title xml:lang="en">CA: 6.1843 ARS = 1 CAD 2014-01-06 Bank of Canada noon rate</title>
<cb:statistics>
<cb:country>CA</cb:country>
<cb:exchangeRate>
<cb:value decimals="4">6.1843</cb:value>
<cb:baseCurrency>CAD</cb:baseCurrency>
<cb:targetCurrency>ARS</cb:targetCurrency>
<cb:rateType>Bank of Canada noon rate</cb:rateType>
<cb:observationPeriod frequency="daily">2014-01-06T12:15:00-05:00</cb:observationPeriod>
</cb:exchangeRate>
</cb:statistics>
</item>
You need to add "cb" to your XmlNamespaceManager in order to use "cb" in SelectSingleNode.
nsmgr.AddNamespace(
"cb",
"http://www.cbwiki.net/wiki/index.php/Specification_1.1");
How do I add a new node to the end of an existing XML file?
I understand how, but how in the end?
For example, I have the following XML file and need to add a new node "entry" to the end of the file:
<?xml version="1.0" encoding="utf-8" ?>
- <entries>
- <entry type="debit">
<amount>100</amount>
<date>11.11.2010</date>
- <description>
- <![CDATA[ Описание записи]]>
</description>
<category>Продукты</category>
</entry>
- <entry type="credit">
<amount>50</amount>
<date>11.11.2010</date>
- <description>
- <![CDATA[ Описание записи]]>
</description>
<category>Продукты</category>
</entry>
- <entry type="debit">
<amount>100</amount>
<date>11.11.2010</date>
- <description>
- <![CDATA[ Описание записи]]>
</description>
<category>Продукты</category>
</entry>
</entries>
The simplest way is to load the XML into memory, append the child node, then write out the whole document again. For example:
XDocument doc = XDocument.Load("before.xml");
doc.Root.Add(new XElement("extra"));
doc.Save("after.xml");
If that isn't exactly what you were after, please clarify your question.
XmlDocument doc = new XmlDocument();
doc.LoadXml("before.xml");
//XmlNode root = doc.DocumentElement;
//Create a new node.
XmlElement elem = doc.CreateElement("entry");
elem.InnerText="";
//Add the node to the document.
//root.AppendChild(elem);
//Console.WriteLine("Display the modified XML...");
doc.LastChild.AppendChild(elem);
doc.Save("before.xml");'
I try many different solution on this site and none seems to work for me .
I getting a xml file from a website and it's returned to me in a string.
using the code below I need to read the nodes in the "entry" section of the xml file.
but it always comes up "0" meaning no nodes found. the only thing left I think is the XML file is not correct?
any help would be great...
------------------code below ------------:
//gets the xml file
string WeatherXML = HttpPost("http://weather.gov/alerts-beta/wwaatmget.php?x=MIC159", "");
//create a xmldoc object..
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
//load the object with the xml file from the web...
doc.LoadXml(WeatherXML);
//go to the main node..
XmlNodeList nodes = doc.SelectNodes("/feed/entry");
//I also tried ....
//doc.SelectNodes("//feed/entry");
//doc.SelectNodes("/entry");
//doc.SelectNodes("//entry");
//loop through the nodes (here is where the nodelist is always empty..
foreach (XmlNode node in nodes)
{
string msgType = node["cap:msgType"].InnerText;
string areaDesc = node["cap:areaDesc"].InnerText;
string summary = node["summary"].InnerText;
string title = node["title"].InnerText;
string link = node["link"].InnerText;
}
------------------------------XML file below------------------
<?xml version = '1.0' encoding = 'UTF-8' standalone = 'no'?>
<!--
This atom/xml feed is an index to active advisories, watches and warnings issued
by the National Weather Service. This index file is not the complete Common
Alerting Protocol (CAP) alert message. To obtain the complete CAP alert,
please follow the links for each entry in this index. Also note the CAP
message uses a style sheet to convey the information in a human readable
format. Please view the source of the CAP message to see the complete data
set. Not all information in the CAP message is contained in this index of
active alerts.
-->
<feed
xmlns = 'http://www.w3.org/2005/Atom'
xmlns:cap = 'urn:oasis:names:tc:emergency:cap:1.1'
xmlns:ha = 'http://www.alerting.net/namespace/index_1.0'
>
<!-- http-date = Sun, 22 Aug 2010 07:06:00 GMT -->
<id>http://www.weather.gov/alerts-beta/wwaatmget.php?x=MIC159</id>
<generator>
NWS CAP Server
</generator>
<updated>2010-08-22T19:06:00-04:00</updated>
<author>
<name>
w-nws.webmaster#noaa.gov
</name>
</author>
<title>
Current Watches, Warnings and Advisories for Van Buren (MIC159) Michigan Issued by the National Weather Service
</title>
<link href='http://www.weather.gov/alerts-beta/wwaatmget.php?x=MIC159'/>
<entry>
<id>http://www.weather.gov/alerts-beta/wwacapget.php?x=MI20100822190600IWXRipCurrentStatementIWX20100823060000MI</id>
<updated>2010-08-22T15:06:00-04:00</updated>
<published>2010-08-22T15:06:00-04:00</published>
<author>
<name>w-nws.webmaster#noaa.gov</name>
</author>
<title>Rip Current Statement issued August 22 at 3:06PM EDT expiring August 23 at 2:00AM EDT by NWS NorthernIndiana http://www.crh.noaa.gov/iwx/</title>
<link href="http://www.weather.gov/alerts-beta/wwacapget.php?x=MI20100822190600IWXRipCurrentStatementIWX20100823060000MI"/>
<summary>...RIP CURRENT RISK REMAINS IN EFFECT UNTIL 2 AM EDT /1 AM CDT/ MONDAY... ...HIGH RISK OF RIP CURRENTS... HIGH WAVES ALONG THE SHORELINE WILL BRING AN INCREASED RISK OF RIP CURRENTS INTO THE EARLY MORNING HOURS OF MONDAY...CREATING DANGEROUS SWIMMING CONDITIONS.</summary>
<cap:effective>2010-08-22T15:06:00-04:00</cap:effective>
<cap:expires>2010-08-23T02:00:00-04:00</cap:expires>
<cap:status>Actual</cap:status>
<cap:msgType>Alert</cap:msgType>
<cap:category>Met</cap:category>
<cap:urgency></cap:urgency>
<cap:severity></cap:severity>
<cap:certainty></cap:certainty>
<cap:areaDesc>Berrien; Cass; La Porte; St. Joseph; Van Buren</cap:areaDesc>
<cap:geocode>
<valueName>FIPS6</valueName>
<value>018091 018141 026021 026027 026159</value>
</cap:geocode>
<cap:parameter>
<valueName>VTEC</valueName>
<value>/O.CON.KIWX.RP.S.0017.000000T0000Z-100823T0600Z/</value>
</cap:parameter>
</entry>
</feed>:"
It’s because your XML root node has a namespace. The following should work:
//load the object with the xml file from the web...
doc.LoadXml(WeatherXML);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("m", "http://www.w3.org/2005/Atom");
//go to the main node..
XmlNodeList nodes = doc.SelectNodes("m:feed", nsMgr);
Console.WriteLine(nodes.Count); // outputs 1
Add the "http://www.w3.org/2005/Atom" namespace to the XPath using an XmlNamespaceManager.
Instead of using regular System.Xml classes you could also use classes from the System.Xml.Linq namespace. Personally I find these a lot easier to use.
var doc = XDocument.Parse(WeatherXml);
var entryNodes = doc.Descendants(
XName.Get("entry", "http://www.w3.org/2005/Atom"));
This will give you a collection of entry nodes from the document.