Unable to get values from xml nodes - c#

I am trying to parse through xml and get some values and have tried multiple approaches but i am unable to get the values.
this is what i have tried so far
string fileName = #"C:\Users\one\OneDrive\Desktop\PP\SnippetWithImage.idms";
string xmlString = System.IO.File.ReadAllText(fileName);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(fileName);
XmlNodeList spreadNodes = xmlDoc.GetElementsByTagName("spread");
foreach (XmlNode spreadNode in spreadNodes)
{
var linkNodes = spreadNode.SelectNodes("//rectangle/image/link");
foreach (XmlNode linkNode in linkNodes)
{
Console.WriteLine("path : " + linkNode.SelectSingleNode("LinkResourceURI").InnerText);
}
}
Here spreadNodes count is always 0.
I have tried this with XElements as well and used Decendents but sill the same result.
Here is the xml structure https://codebeautify.org/xmlviewer/y22db1f26
the file which i am loading is an InDesign Snippet file. I am trying to get the linkResourceURI property value from links which is a child of image which is a child of rectangle which is a child of spread.

Some quick debugging shows that spreadNodes is empty, to start with. The most obvious cause is that the element name is Spread not spread, and if we make this change, we see spreadNodes has one element.
Next, it's obvious that spreadNode.SelectNodes("//rectangle/image/link") isn't returning anything. Again, that's probably capitalisation: change it to //Rectangle/Image/Link, and we get a NullReferenceException. Progress, at least.
We're getting that exception because linkNode.SelectSingleNode("LinkResourceURI") is returning null. It turns out that's because LinkResourceURI is an attribute, and you're looking for an element. Change that to linkNode.Attributes["LinkResourceURI"].InnerText, and everything works as expected.
XmlNodeList spreadNodes = xmlDoc.GetElementsByTagName("Spread");
foreach (XmlNode spreadNode in spreadNodes)
{
var linkNodes = spreadNode.SelectNodes("//Rectangle/Image/Link");
foreach (XmlNode linkNode in linkNodes)
{
Console.WriteLine("path : " + linkNode.Attributes["LinkResourceURI"].InnerText);
}
}

Related

Failing to read value XML attribute in C#

I am trying to read a file produced by another developer. The file looks something like this. I am trying to read in the value for 'ProfileName', but when I look at the object in memory, I see null for the Value (capital V) attribute. The only place I can see the string "GolfLeague-Dual" is in the outerxml attribute, but I would have to parse through a bunch of just to get it.
<?xml version="1.0"?>
<TopNode>
<ProfileSettings>
<ProfileName value="GolfLeague-Dual" />
</ProfileSettings>
</TopNode>
Here is my code to try to read this:
XmlDocument doc = new XmlDocument();
doc.Load(directory + #"\Settings.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//ProfileSettings");
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Value);
}
Your code is trying to get the inner value of the node, not an attribute called value. Try this instead...
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Attributes["value"].Value);
}
Here's a working dotnetfiddle...
https://dotnetfiddle.net/pmJKbX

return xml node that do not have specific child elements

I have the following code which is returning all nodes and thier values.
I only want to return nodes that do no have certain child nodes.
MY code base I am working from is
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*", nsmgr);
foreach (XmlNode node in nodelist)
{
strNode = node.Name;
strValue = node.InnerText;
responseString += strNode + " " + strValue + "\r\n ";
}
return responseString;
So I only what to return /propschema/* if the /propschema/ child does not contain a certain child node. For my example i do not want to return the propshema node if there is a child node of or
I had though I should be using something like
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*[not (count[system>0])", nsmgr);
But that is failing with an error of invalid token
'//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*[not (count[system>0])' has an invalid token.
What am I doing wrong here? Am I missing syntax, "", or something else?
I have determined that if I can use a filter in the XPATH I would be applying it at the wrong point.
I want to return all propschema nodes and thier children except if the proschema had a child node of . So I need to put the filer earlier
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema[filter for system]/DAV:*", nsmgr);
But whenever I try to use a 'not' or type of filter I get a token error.
Is it possible to filter directly in the XPATH?

Pasting xml to console

I need to get data SHILS_V from XML file. I read .xml
XML code for example:
<SVED_PR_GS>
<ZGLV>
<VERSION>99</VERSION>
<DATA>9999</DATA>
<FILENAME>1234</FILENAME>
<FIRSTNAME>1234</FIRSTNAME>
</ZGLV>
<SVD>
<CODE></CODE>
<YEAR></YEAR>
<MONTH></MONTH>
</SVD>
<SV_PR_GS>
<OBSV>
<N_ZAP>1</N_ZAP>
<MO_SV_V>12345</MO_SV_V>
<SNILS_V>123456789</SNILS_V>
</OBSV>
</SV_PR_GS>
</SVED_PR_GS>
My code to read xml:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("SVED_PR_GS/SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n["OBSV/SNILS_V"];
Console.WriteLine("Snils V: " + snils_v);
}
Where is the problem?
How to get the information from SNILS_V?
GetElementsByTagName expects a tagname, not an XPath expression, "SV_PR_GS" will work there. And the same goes for the indexer of your XmlNode instance called n, this XPath will not work n["OBSV/SNILS_V"], use a tagname there as well but you have to handle the extra OBSV child there.
Here is your adapted code that produces output for me:
XmlNodeList nodes = xml.GetElementsByTagName("SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
// first get the OBSV element
XmlNode obsv = n["OBSV"];
// now we can reach the other childs
XmlNode snils_v = obsv["SNILS_V"];
// Value will be null for XmlElement types, use InnerText instead
Console.WriteLine("Snils V: {0}" , snils_v.InnerText);
}
Notice that the Value property will return null for XmlNode that are of type XmlElement. In the XmlNode.Value documentation it is stated:
null. You can use the XmlElement.InnerText or XmlElement.InnerXml properties to access the value of the element node.
As your SNILS_V element seem to contain just a value InnerText is appropriate here.
To select a single node from XML. You need to access that object using SelectSingleNode method.
xml.SelectSingleNode("xpath for node")
To get collection of nodes you can write
xml.SelectNodes("xpath for node collection")
You should be able to get the value as follows:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("OBSV");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n.SelectSingleNode("SNILS_V");
Console.WriteLine("Snils V: " + snils_v.InnerText);
}

Create loops and parsing XML nodes value for Selenium tests

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.

XDocument, it says that a node is text but it is an element

I am reading an XML that contains a tag like this:
<source><bpt id="1"><donottranslate></bpt><ph id="2">($ T_353_1 Parent ID $)</ph><ept id="1"></donottranslate></ept></source>
When reading source node I get that this node type is Text, but it should be Element.
This is an XML that I am receiving and I cannot change it.
Do you know how can I get this sorted out?
This is my code:
XDocument doc = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
foreach (var elUnit in doc.Descendants("trans-unit"))
{
if (elUnit.AttributeString("translate").ToString() == "no")
{
foreach (var elSource in elUnit.Elements("source"))
{
string text = "";
foreach (var node in elSource.DescendantNodes().Where(n => XmlNodeType.Text == n.NodeType).ToList())
{
//When reading that "source" node, it enters inside this code
Thanks
First check whether your XML is wellformed
http://www.w3schools.com/xml/xml_validator.asp
http://chris.photobooks.com/xml/default.htm
I could get this to work
//using System.Xml.Linq;
var str = "<source><bpt id=\"1\"><donottranslate></bpt>" +
"<ph id=\"2\">($ T_353_1 Parent ID $)</ph>" +
"<ept id=\"1\"></donottranslate></ept></source>";
XElement element = XElement.Parse(str);
Console.WriteLine(element);
The output is this
<source>
<bpt id="1"><donottranslate></bpt>
<ph id="2">($ T_353_1 Parent ID $)</ph>
<ept id="1"></donottranslate></ept>
</source>
Please provide some code sample for more help if this example if not suffient.
Finally, I solved this checking if the node is correct or not:
if (System.Security.SecurityElement.IsValidText(text.XmlDecodeEntities()))

Categories

Resources