Okay, silly question here, but I'm just starting with xml.
<fifth points = '500' answer = 'Ada Lovelace'>
This woman, known as the world's first computer programmer
was also a Countess.
</fifth>
How exactly do I get at the data after Ada Lovelace? I understand that fifth is the node, and that points and answer are the attributes. What must I grab to get the desired data?
here is something you can try and test to help you understand how to get at the node.InnerText
var testDoc =
#"<fifth points = '500' answer = 'Ada Lovelace'>"
+ "This woman, known as the world's first computer programmer "
+ "was also a Countess."
+ "</fifth>";
XmlDocument docXML = new XmlDocument();
docXML.LoadXml(testDoc);
var innerxml = docXML.InnerText;
MessageBox.Show(innerxml);
You're probably looking for something like:
node.InnerText
To learn about parsing nodes XML in C#, read up on http://www.csharp-examples.net/xml-nodes-by-name/ . This post, http://www.codeproject.com/Articles/7718/Using-XML-in-C-in-the-simplest-way may also be helpful as well, as it provides some of the simplest ways of parsing XML in C#.
You can simply index XmlNode with the node name: xmlNode["FirstName"].InnerText. See the example below.
XmlDocument xml = new XmlDocument();
// suppose that myXmlString contains "<Names>...</Names>":
xml.LoadXml(myXmlString);
XmlNodeList xnList = xml.SelectNodes("/Names/Name");
foreach (XmlNode xn in xnList)
{
string firstName = xn["FirstName"].InnerText;
string lastName = xn["LastName"].InnerText;
Console.WriteLine("Name: {0} {1}", firstName, lastName);
}
The output is:
Name: John Smith Name: James White
Edit: It's important to note that DJ KRAZE and Jeremy Thompson also inspired my answer.
You can use Linq to Xml. If this is a full xml you need to parse:
var xml = "<fifth points='500' answer='Ada Lovelace'>This woman, known as the world's first computer programmer was also a Countess.</fifth>";
XElement element = XElement.Parse(xml);
string text = (string)element; // takes element's innerText
If you need to select this element from your xml file by answer attribute value:
XDocument xdoc = XDocument.Load(path_to_xml_file);
string text = xdoc.Descendants("fifth")
.Where(e => (string)e.Attribute("answer") == "Ada Lovelace")
.Select(e => (string)e)
.FirstOrDefault(); // returns first matched element or null
Related
Please read the code bellow. There I am trying to grab all elements under the <GetSellerListResponse> node, then my goal is to grab TotalNumberOfPages value (currently it's 9 as you can see in the XML).
But my problem is I am getting an error:
System.InvalidOperationException: 'Sequence contains no elements'
Error screenshot is attached for better understanding. Can you tell me what's wrong the way I am trying to grab all elements? Also if possible can you tell how I can grab that 9 from TotalNumberOfPage?
Thanks in advance
C#:
var parsedXML = XElement.Parse(xml);
var AllElements = parsedXML.Descendants("GetSellerListResponse")
.Where(x => x.Attribute("xmlns").Value.Equals("urn:ebay:apis:eBLBaseComponents"))
.First();
XML:
<?xml version="1.0" encoding="UTF-8"?>
<GetSellerListResponse xmlns="urn:ebay:apis:eBLBaseComponents">
<Timestamp>2018-06-20T17:26:29.518Z</Timestamp>
<Ack>Success</Ack>
<Version>1059</Version>
<Build>E1059_CORE_APISELLING_18694654_R1</Build>
<PaginationResult>
<TotalNumberOfPages>9</TotalNumberOfPages>
</PaginationResult>
</GetSellerListResponse>
EDIT: your mistake is the usage of XElement: it is searching for matching elements in the children of <GetSellerListResponse>; that's why you are not getting any result. Change XElement.Parse(xml); to XDocument.Parse(xml);, then the following snippets will work.
You could simply check for the local name:
var AllElements = parsedXML.Descendants().First(x => x.Name.LocalName == "GetSellerListResponse");
I would suggest to use XDocument instead of XElement for parsedXML, because you could shorten the above query to var AllElements = parsedXML.Root;
Another thing you could try is prepending the namespace:
XNamespace ns = "urn:ebay:apis:eBLBaseComponents";
var AllElements = parsedXML.Descendants(ns + "GetSellerListResponse").First();
To answer the question "how to get the number of pages":
var pages = AllElements.Element(ns + "PaginationResult").Element(ns + "TotalNumberOfPages").Value;
I would suggest using the XmlDocument class from System.Xml.
Try the code below:
XmlDocument doc = new XmlDocument();
doc.LoadXml("<GetSellerListResponse xmlns=\"urn:ebay:apis:eBLBaseComponents\"><Timestamp>2018-06-20T17: 26:29.518Z</Timestamp><Ack>Success</Ack><Version>1059</Version><Build>E1059_CORE_APISELLING_18694654_R1</Build><PaginationResult><TotalNumberOfPages>9</TotalNumberOfPages></PaginationResult></GetSellerListResponse>");
XmlNodeList nodeList = doc.GetElementsByTagName("TotalNumberOfPages");
In this case, your nodeList will have just the one element for TotalNumberOfPages and you can access the value by checking
nodeList.FirstOrDefault().InnerText
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
I am trying to write a test function in C# that read data from an XML file and parse into Selenium testing methods , the XML code is like:
<home>
<ask_frame>
<button>
<id>Object ID<id>
<xpath>Object XPath<xpath>
<textbox>
<id>Object ID<id>
<xpath>Object XPath<xpath>
</ask_frame>
<search_frame>
<id>Object ID<id>
<xpath>Object XPath<xpath>
</search_frame>
<home>
I am trying to create a loop that read the id and xpath value from these nodes and parse them into an method for searching a webpage element by id and xpath. My initial attempt was:
Code updated
public void CheckIdTest()
{
driver.Navigate().GoToUrl(baseURL + "FlightSearch");
XmlDocument xd = new XmlDocument();
xd.Load(#"C:\XMLFile1.xml");
XmlNodeList mainlist = xd.SelectNodes("//home/*");
XmlNode mainroot = mainlist[0];
foreach (XmlNode xnode in mainroot)
{
string objID = xnode.SelectSingleNode("id").InnerText;
string objXPath = xnode.SelectSingleNode("XPath").InnerText;
objID = objID.Trim();
objXPath = objXPath.Trim();
String checkValue = "ObjID value is: " + objID + Environment.NewLine+ "ObjXPath value is: " + objXPath;
System.IO.File.WriteAllText(#"C:\checkvalue.txt", checkValue);
objectCheck(objXPath, objID);
}
}
I have put a String and checked that correct values for ObjID and ObjXPath have been achieved, but this loop also went only twice (checked 2 nodes in first branch). How could I make it runs through every node in my XML?
Any suggestions and explanations to the code will be highly appreciated.
Basically these two lines are using incorrect XPath :
XmlNodeList idlist = xd.SelectNodes("id");
XmlNodeList xpathlist = xd.SelectNodes("XPath");
<id> and <xpath> nodes aren't located directly at the root level, so you can't access it just like above. Besides, xpath is case-sensitive so you should've used "xpath" instead of "XPath". Try to fix it like this :
XmlNodeList idlist = xd.SelectNodes("//id");
XmlNodeList xpathlist = xd.SelectNodes("//xpath");
or more verbose :
XmlNodeList idlist = xd.SelectNodes("home/*/id");
XmlNodeList xpathlist = xd.SelectNodes("home/*/xpath");
UPDATE :
Responding to your comment about looping problem, I think you want to change it like this :
foreach (XmlNode xnode in mainroot.ChildNodes)
{
string objID = xnode.SelectSingleNode("id").InnerText;
string objXPath = pathroot.SelectSingleNode("xpath").InnerText;
objectCheck(objID, objXPath);
}
You are getting this error because you are trying to use an object that is null i.e not instantiated.
Put in a breakpoint at the line
XmlDocument xd = new XmlDocument();
and step through line by line till you find where the nothing.null reference is.
It should not take long to find out what the problem is.
Considering the following XML:
<Stations>
<Station>
<Code>HT</Code>
<Type>123</Type>
<Names>
<Short>H'bosch</Short>
<Middle>Den Bosch</Middle>
<Long>'s-Hertogenbosch</Long>
</Names>
<Country>NL</Country>
</Station>
</Stations>
There are multiple nodes. I need the value of each node.
I've got the XML from a webpage (http://webservices.ns.nl/ns-api-stations-v2)
Login (--) Pass (--)
Currently i take the XML as a string and parse it to a XDocument.
var xml = XDocument.Parse(xmlString);
foreach (var e in xml.Elements("Long"))
{
var stationName = e.ToString();
}
You can retrieve "Station" nodes using XPath, then get each subsequent child node using more XPath. This example isn't using Linq, which it looks like you possibly are trying to do from your question, but here it is:
XmlDocument xml = new XmlDocument();
xml.Load(xmlStream);
XmlNodeList stations = xml.SelectNodes("//Station");
foreach (XmlNode station in stations)
{
var code = station.SelectSingleNode("Code").InnerXml;
var type = station.SelectSingleNode("Type").InnerXml;
var longName = station.SelectSingleNode("Names/Long").InnerXml;
var blah = "you should get the point by now";
}
NOTE: If your xmlStream variable is a String, rather than a Stream, use xml.LoadXml(xmlStream); for line 2, instead of xml.Load(xmlStream). If this is the case, I would also encourage you to name your variable to be more accurately descriptive of the object you're working with (aka. xmlString).
This will give you all the values of "Long" for every Station element.
var xml = XDocument.Parse(xmlStream);
var longStationNames = xml.Elements("Long").Select(e => e.Value);
Having problems getting NodeList.SelectSingleNode() to work properly.
My XML looks like this:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<inm:Results xmlns:inm="http://www.namespace.com/1.0">
<inm:Recordset setCount="18254">
<inm:Record setEntry="0">
<!-- snip -->
<inm:Image>fileName.jpg</inm:Image>
</inm:Record>
</inm:Recordset>
</inm:Results>
The data is a long series of <inm:Record> entries.
I open the doc and get create a NodeList object based on "inm:Record". This works great.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNodeList xRecord = xdoc.GetElementsByTagName("inm:Record");
I start looping through the NodeList using a for loop. Before I process a given entry, I want to check and see if the <inm:Image> is set. I thought it would be super easy just to do
string strImage = xRecord[i].SelectSingleNode("inm:Image").InnerText;
My thinking being, "For the XRecord that I'm on, go find the <inm:Image> value ...But this doesn't work as I get the exception saying that I need a XmlNameSpaceManager. So, I tried to set that up but could never get the syntax right.
Can someone show me how to use the correct XmlNameSpaceManager syntax in this case.
I've worked around the issue for now by looping through all of the childNodes for a given xRecord, and checking the tag once I loop around to it. I would like to check that value first to see if I need to loop over that <inm:Record> entry at all.
No need to loop through all the Record elements, just use XPath to specify the subset that you want:
XmlDocument xdoc = new XmlDocument();
xdoc.Load(openFileDialog1.FileName);
XmlNamespaceManager manager = new XmlNamespaceManager(xdoc.NameTable);
manager.AddNamespace("inm", "http://www.inmagic.com/webpublisher/query");
XmlNodeList nodes = xdoc.SelectNodes("/inm:Results/inm:Recordset/inm:Record[inm:Image != '']", manager);
Using the LINQ to XML libraries, here's an example for retrieving that said node's value:
XDocument doc = XDocument.Load(openFileDialog1.FileName);
List<XElement> docElements = doc.Elements().ToList();
XElement results = docElements.Elements().Where(
ele => ele.Name.LocalName == "Results").First();
XElement firstRecord = results.Elements().Where(
ele => ele.Name.LocalName == "Record").First();
XElement recordImage = firstRecord .Elements().Where(
ele => ele.Name.LocalName == "Image").First();
string imageName = recordImage.Value;
Also, by the way, using Hungarian notation for a type-checked language is overkill. You don't need to prepend string variables with str when it will always be a string.
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
string strImage = xRecord[i].SelectSingleNode("inm:Image",nsMgr).InnerText;
Should do it.
Using this Xml library, you can get all the records that have an Image child element with this:
XElement root = XElement.Load(openFileDialog1.FileName);
XElement[] records = root.XPath("//Record[Image]").ToArray();
If you want to be sure that the Image child contains a value, it can be expressed like this:
XElement[] records = root.XPath("//Record[Image != '']").ToArray();