Get a specific value in an xml document with c# - c#

I want to grab one specific value within an XML document at a url, I have managed to get a list of all values, but I'm not sure how to choose the specific value. The XML document is as follows;
<evec_api version="2.0" method="marketstat_xml">
<marketstat>
<type id="37">
<buy>
<volume>291092912</volume>
<avg>137.11</avg>
<max>156.06</max>
<min>53.46</min>
<stddev>31.00</stddev>
<median>140.28</median>
<percentile>156.05</percentile>
</buy>
<sell>
<volume>273042044</volume>
<avg>177.43</avg>
<max>339.00</max>
<min>166.22</min>
<stddev>30.83</stddev>
<median>170.38</median>
<percentile>166.26</percentile>
</sell>
<all>
<volume>574134956</volume>
<avg>154.64</avg>
<max>339.00</max>
<min>43.00</min>
<stddev>42.21</stddev>
<median>156.05</median>
<percentile>69.98</percentile>
</all>
</type>
</marketstat>
</evec_api>
The specific value I want is the min sell value, being 166.22. My code at current, which just retrieves all values in the document is
private void Form1_Load(object sender, EventArgs e)
{
string xmlDocPath = "http://api.eve-central.com/api/marketstat?typeid=37&regionlimit=10000002&usesystem=30000142";
XmlTextReader xmlReader = new XmlTextReader(xmlDocPath);
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Text)
{
textBox1.AppendText(xmlReader.Value + "\n");
}
}
}
I've tried a few different methods, like just throwing it all in a text box and taking the specific line, but that seems like a really silly solution. Most of the tutorials use console however that doesn't work for me. I feel it's probably a simple solution, but I'm yet to find one that works. Also, being fairly new to this, if there is anything terribly inefficient about this code, feel free to point it out.

Try to use LINQ to XML, it's very straightforward. Example is given below:
var doc = XDocument.Parse(xml); //use XDocument.Load if you have path to a file
string minSell = doc.Descendants("sell")
.First()
.Element("min")
.Value;
Console.WriteLine(minSell); //prints 166.22

If you wrap that XmlTextReader into a XmlDocument you can then execute an XPath query on it to retrieve the specific node you're interested in:
var doc = new XmlDocument(xmlReader);
doc.Load();
var xpath = "/marketstat/type [#id='37']/sell/min";
var myNode = doc.SelectSingleNode(xpath);

Related

Trying to read particular Xml value using C#

I'm new with C#. please help me.
data.xml
<?xml version="1.0" standalone="yes"?>
<DataSet1 xmlns="http://tempuri.org/DataSet1.xsd">
<Language>
<Id>001</Id>
<English>"Welcome to India"</English>
<German>"Willkommen in Indien"</German>
</Language>
</DataSet1>
How to read value of Id using C# Xml? I'm new with C#. please help me.
My effort:
XmlDocument doc = new XmlDocument();
XmlReader reader = XmlReader.Create(#"D:\data.xml");
while(reader.Read())
{
reader.MoveToContent();
if (reader.IsStartElement("DataSet1"))
{
reader.ReadToDescendant("Language");
string str2 = reader.Name.ToString();
MessageBox.Show(str2);
}
}
I'd strongly advise you to use LINQ to XML, which is a much simpler API than XmlDocument, and has excellent namespace support. Here's an example to get the Id value with LINQ to XML:
using System;
using System.Xml.Linq;
public class Program
{
public static void Main()
{
XDocument doc = XDocument.Load("test.xml");
XNamespace ns = "http://tempuri.org/DataSet1.xsd";
string id = doc.Root // From the root...
.Element(ns + "Language") // select the Language direct child...
.Element(ns + "Id") // and the Id child of that...
.Value; // and then take the text value
Console.WriteLine(id);
}
}
Obviously if your XML doesn't just have a single Language element you'll need to pick the right one, etc. You should read the LINQ to XML documentation for more information.
Use XmlDocument, if you Need further help leave a comment :)
XmlDocument xdoc = new XmlDocument("YourXmlString");
XmlNodeList xNodes = xdoc.GetElementsByTagName("Id");
string Wished = xNodes[0].InnerText;
Little bit of explanation:
I recommend XmlDocument a lot because I really like to work with it myself, and besides that it has some pretty neat features to explore. Besides that, it is easy to get or to iterate through nodes

GetElementByTagName returns System.Xml.XmlElementList

I have an XML document that looks like this
<?xml version="1.0" encoding="utf-8" ?>
<event>
<name>Test Event</name>
<date>07/09/1997</date>
<description>Birthday</description>
<blogURL></blogURL>
</event>
I want to grab these fields and display them in ASP:Labels
This is my code behind
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument pressRelease = new XmlDocument();
pressRelease.Load(Server.MapPath("~/PressSection.xml"));
XmlNodeList name = pressRelease.GetElementsByTagName("name");
CurrentEventName.Text = name.ToString();
}
But this is what it displays in the label
System.Xml.XmlElementList
Not really sure what I'm doing wrong.
As the name might suggest and, as the documentation tells you, the method returns:
An XmlNodeList containing a list of all matching nodes. If no nodes match name, the returned collection will be empty.
You need to iterate that list, or simply take the first item if you're sure one will always be there:
var names = pressRelease.GetElementsByTagName("name");
CurrentEventName.Text = names[0].Value;
That said, LINQ to XML is a far nicer API, I would definitely encourage you to learn more about it:
var doc = XDocument.Load(Server.MapPath("~/PressSection.xml"));
CurrentEventName.Text = (string)doc.Descendants("name").Single();
try this way
XDocument doc = XDocument.Load(Server.MapPath("~/PressSection.xml"));
var query = doc.Descendants("event").Elements("name").FirstOrDefault();
Console.WriteLine(query.Value);
This is actually the intended behavior.
The reason for it is that it returns a list of all elements that match your criteria. If you know for sure that you'll always want the first element, you could always get the first element by:
name[0].ToString()
However, you might also want to add some null and empty checking for the XmlElementList as it may also be empty, which will result in you getting a null pointer exception if you try to get an item from it.

I'm unable to extract the Data from this XML

I'm currently working on a small weather application in C#. To do this, I need to extract data from this xml file: http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D%22london%22&format=xml
In this specific case I need the value of the first /query/results/place/woeid node. I've been looking around and tried many different methods, but didn't manage to get any values with any of those. My current code looks like this:
string query = String.Format("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D%22london%22&format=xml");
XmlDocument xml = new XmlDocument();
xml.Load(query);
XmlNodeList nodeList = wData.DocumentElement.SelectNodes("/query/results/place");
foreach (XmlNode node in nodeList)
{
return node.SelectSingleNode("woeid").InnerText;
}
return "NO WOEID FOUND!";
I'm just starting to learn C# so I might do some stupid mistakes. Still, I would really appreciate any kind of help.
You can use XDocument
string query = String.Format("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20geo.places%20where%20text%3D%22london%22&format=xml");
XDocument xml = XDocument.Load(query);
XNamespace ns = "http://where.yahooapis.com/v1/schema.rng";
var woeid = xml.Element("query").Element("results").Elements(ns + "place").FirstOrDefault().Element(ns +"woeid").Value;
Make sure you check if there are any elements in the XDocuments

Find and delete all occurrences of a string that starts with x

I'm parsing an XML file, to compare it to another XML file. XML Diff works nicely, but we have found there are a lot of junk tags that exist in one file, not in the other, that have no bearing on our results, but clutter up the report. I have loaded the XML file into memory to do some other things to it, and I'm wondering if there is an easy way at the same time to go through that file, and remove all tags that start with, as an example color=. The value of color is all over the map, so not easy to grab them all remove them.
Doesn't seem to be any way in XML Diff to specify, "ignore these tags".
I could roll through the file, find each instance, find the end of it, delete it out, but I'm hoping there will be something simpler. If not, oh well.
Edit: Here's a piece of the XML:
<numericValue color="-103" hidden="no" image="stuff.jpg" key="More stuff." needsQuestionFormatting="false" system="yes" systemEquivKey="Stuff." systemImage="yes">
<numDef increment="1" maximum="180" minimum="30">
<unit deprecated="no" key="BPM" system="yes" />
</numDef>
</numericValue>
If you are using Linq to XML, you can load your XML into an XDocument via:
var doc = XDocument.Parse(xml); // Load the XML from a string
Or
var doc = XDocument.Load(fileName); // Load the XML from a file.
Then search for all elements with matching names and use System.Xml.Linq.Extensions.Remove() to remove them all at once:
string prefix = "L"; // Or whatever.
// Use doc.Root.Descendants() instead of doc.Descendants() to avoid accidentally removing the root element.
var elements = doc.Root.Descendants().Where(e => e.Name.LocalName.StartsWith(prefix, StringComparison.Ordinal));
elements.Remove();
Update
In your XML, the color="-103" substring is an attribute of an element, rather than an element itself. To remove all such attributes, use the following method:
public static void RemovedNamedAttributes(XElement root, string attributeLocalNamePrefix)
{
if (root == null)
throw new ArgumentNullException();
foreach (var node in root.DescendantsAndSelf())
node.Attributes().Where(a => a.Name.LocalName == attributeLocalNamePrefix).Remove();
}
Then call it like:
var doc = XDocument.Parse(xml); // Load the XML
RemovedNamedAttributes(doc.Root, "color");

XPathSelectElements returns null

Load function is already defined in xmlData class
public class XmlData
{
public void Load(XElement xDoc)
{
var id = xDoc.XPathSelectElements("//ID");
var listIds = xDoc.XPathSelectElements("/Lists//List/ListIDS/ListIDS");
}
}
I'm just calling the Load function from my end.
XmlData aXmlData = new XmlData();
string input, stringXML = "";
TextReader aTextReader = new StreamReader("D:\\test.xml");
while ((input = aTextReader.ReadLine()) != null)
{
stringXML += input;
}
XElement Content = XElement.Parse(stringXML);
aXmlData.Load(Content);
in load function,im getting both id and and listIds as null.
My test.xml contains
<SEARCH>
<ID>11242</ID>
<Lists>
<List CURRENT="true" AGGREGATEDCHANGED="false">
<ListIDS>
<ListID>100567</ListID>
<ListID>100564</ListID>
<ListID>100025</ListID>
<ListID>2</ListID>
<ListID>1</ListID>
</ListIDS>
</List>
</Lists>
</SEARCH>
EDIT: Your sample XML doesn't have an id element in the namespace with the nss alias. It would be <nss:id> in that case, or there'd be a default namespace set up. I've assumed for this answer that in reality the element you're looking for is in the namespace.
Your query is trying to find an element called id at the root level. To find all id elements, you need:
var tempId = xDoc.XPathSelectElements("//nss:id", ns);
... although personally I'd use:
XDocument doc = XDocument.Parse(...);
XNamespace nss = "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner";
// Or use FirstOrDefault(), or whatever...
XElement idElement = doc.Descendants(nss + "id").Single();
(I prefer using the query methods on LINQ to XML types instead of XPath... I find it easier to avoid silly syntax errors etc.)
Your sample code is also unclear as you're using xDoc which hasn't been declared... it helps to write complete examples, ideally including everything required to compile and run as a console app.
I am looking at the question 3 hours after it was submitted and 41 minutes after it was (last) edited.
There are no namespaces defined in the provided XML document.
var listIds = xDoc.XPathSelectElements("/Lists//List/ListIDS/ListIDS");
This XPath expression obviously doesn't select any node from the provided XML document, because the XML document doesn't have a top element named Lists (the name of the actual top element is SEARCH)
var id = xDoc.XPathSelectElements("//ID");
in load function,im getting both id and and listIds as null.
This statement is false, because //ID selects the only element named ID in the provided XML document, thus the value of the C# variable id is non-null. Probably you didn't test thoroughly after editing the XML document.
Most probably the original ID element belonged to some namespace. But now it is in "no namespace" and the XPath expression above does select it.
string xmldocument = "<response xmlns:nss=\"http://schemas.microsoft.com/SQLServer/reporting/reportdesigner\"><action>test</action><id>1</id></response>";
XElement Content = XElement.Parse(xmldocument);
XPathNavigator navigator = Content.CreateNavigator();
XmlNamespaceManager ns = new XmlNamespaceManager(navigator.NameTable);
ns.AddNamespace("nss", "http://schemas.microsoft.com/SQLServer/reporting/reportdesigner");
var tempId = navigator.SelectSingleNode("/id");
The reason for the null value or system returned value is due to the following
var id = xDoc.XPathSelectElements("//ID");
XpathSElectElements is System.xml.linq.XElment which is linq queried date. It cannot be directly outputed as such.
To Get individual first match element
use XPathSelectElement("//ID");
You can check the number of occurrences using XPathSelectElements as
var count=xDoc.XPathSelectElements("//ID").count();
you can also query the linq statement as order by using specific conditions
Inorder to get node value from a list u can use this
foreach (XmlNode xNode in xDoc.SelectNodes("//ListIDS/ListID"))
{
Console.WriteLine(xNode.InnerText);
}
For Second list you havnt got the value since, the XPath for list items is not correct

Categories

Resources