Read the XML with different elements in C# - c#

I know, that there are a lot of question about parsing C#, but I couldn't find answer.
So, I need to write a DLL for parsing XML, but with some features, as I don't know what elements are in XML file. I need to parse all nodes of file and their elements. How can I do it? Now, I'm working with simple file
<reg>
<email_login>paykforcycvert#reincarnate.com</email_login>
<email_password>nDOUn3TybD</email_password>
</reg>
and my dll code now is
public XmlNodeList GetElementsName(string path)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("email_login");
return nodeList;
}
It should return "paykforcycvert#reincarnate.com".
My console app:
XMLWorker worker = new XMLWorker();
string path = "file:///D:/temp/test.xml";
XmlNodeList nodeList = worker.GetElementsName(path);
for (int i = 0; i < nodeList.Count; i++)
Console.WriteLine(nodeList[i].InnerText);
Console.ReadLine();
But it returns "paykforcycvert#reincarnate.comnDOUn3TybD"
How can I parse differently?

Use LINQ to XML:
XElement reg = XElement.Load(path);
string login = (string)reg.Element("email_login");
BTW your code works fine for me. Make sure you are not selecting all elements instead of email_login only. I.e. if you are getting child nodes XmlNodeList nodeList = xmlDoc.ChildNodes; instead of getting elements by tag name, then you will have your results.
Or possibly you have several elements named as email_login. E.g. following xml will produce your results with your code:
<reg>
<email_login>paykforcycvert#reincarnate.com</email_login>
<email_login>nDOUn3TybD</email_login>
</reg>

i ran the exact same code you gave and got paykforcycvert#reincarnate.com as output so my guess is that you haven't build your project after you fixed something or it wasn't cleaned.
try to clean the project and run it again

You can do it this way
public List<String> getElementValues(string path,string elementName)
{
XElement doc= XElement.Load(path);
var elementList=doc.Descendants().Elements();
return elementList.Where(x=>x.Name.LocalName==elementName)
.Select(y=>y.Value)
.ToList();
}
You can now get all the values of element with name email_login
var values=getElementValues(path,"email_login");

I ran following code after coping the XML data you provided in XMLFile.xml to emulate output:
class Program
{
static void Main(string[] args)
{
XMLWorker worker = new XMLWorker();
//
string path = #"C:\Users\abc\Desktop\ConsoleApplication1\ConsoleApplication1\XMLFile.xml";
XmlNodeList nodeList = worker.GetElementsName(path);
for (int i = 0; i < nodeList.Count; i++)
Console.WriteLine(nodeList[i].InnerText);
Console.ReadLine();
}
}
public class XMLWorker
{
public XmlNodeList GetElementsName(string path)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(path);
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("email_login");
return nodeList;
}
}
But for me it is working fine.

You can also use XPath query:
XmlNodesList nodesList = xmlDoc.SelectNodes("//email_login"));
foreach(string oneNode in nodesList)
{
Console.Write(oneNode.InnerText);
}

Related

Insert a string in a particular position into an other string

I am work on some innerxml of an XML document.
I have to concat several parts.
I have this:
<TRANFSERT><GOOD></GOOD></TRANSFERT>
I want to insert another part, <GOOD></GOOD>, before </TRANSFERT>.
I tried this:
int pos = xmldoc.indexOf("</GOOD>");
StringBuilder sb = new StringBuilder(xmlFinal);
sb.Append(xmlModifiee,pos,xmlModifiee.length);
xmlFinal = sb.ToString();
But it doesn't work.
How can I add a small part of XML in other XML?
You shouldn't interact with XML like with ordinary string.
Use provided System.Xml.XmlDocument or System.Xml.Linq.XDocument classes:
Ordinary XmlDocument single node selection and appending new element to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
XmlNode goodNode = xmlDocument.SelectSingleNode("TRANSFERT/GOOD");
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
goodNode.AppendChild(nodeToInsert);
Ordinary XmlDocument iterating by nodes to find necessary (be aware for many-childed nodes) and add new child node to it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load("YourFile.xml");
foreach (XmlNode rootNode in xmlDocument.ChildNodes)
{
if (rootNode.Name == "TRANSFERT")
{
foreach (XmlNode childNode in rootNode.ChildNodes)
{
if (childNode.Name == "GOOD")
{
XmlNode nodeToInsert = xmlDocument.CreateElement("INSERTEDNODE");
childNode.AppendChild(nodeToInsert);
}
}
}
}
Linq to XML variant:
XDocument xDoc = XDocument.Load("YourFIle.xml");
XElement rootElement = xDoc.Element("TRANSFERT");
XElement goodElement = rootElement.Element("GOOD");
goodElement.Add(new XElement("INSERTEDNODE"));
Simplified Linq to XML variant:
XDocument.Load("YourFIle.xml").Element("TRANSFERT").Element("GOOD").Add(new XElement("INSERTEDNODE"));
EDITED: answering the question, example was rewrited from changing InnerText values to Append/Add new child element to GOOD node.
StringBuilder.Append can only be used to add something to the end of the string. To add something inside the string, use StringBuilder.Insert like this:
sb.Insert(pos, xmlModifiee);

XML - Write a single node

I got this function for simply get the inner text of my xml:
XmlDocument document = new XmlDocument();
document.Load("game.xml");
string content = document.SelectSingleNode("Game/Client-Version").InnerText;
(this is the xml file (due to complications with stackoverflow posted on pastebin)): http://pastebin.com/EEeFAJpC
And now I am exactly looking for the function above, just to write. Like
document.WriteSingleNode("Game/Client-Version", "texttowrite");
I did not find anything helping me out.
This should work
XmlElement x = document.SelectSingleNode("Game/Client-Version") as XmlElement;
x.InnerText = "texttowrite";
Create your own extension method:
public void WriteSingleNode(this XmlDocument document, string NodeName, string InnerText)
{
// Create a new element node.
XmlNode newElem = document.CreateNode("element", "pages", "");
newElem.InnerText = InnerText;
Console.WriteLine("Add the new element to the document...");
document.DocumentElement.AppendChild(newElem);
Console.WriteLine("Display the modified XML document...");
Console.WriteLine(document.OuterXml);
}

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.

How do I get a specific value from xml in c#

My problem is a bit typical and I am very new to working with xml. Please view the following code:
XmlDocument xDoc = new XmlDocument();
xDoc.Load(myxml);
Response.Write("<p><strong>First Result</strong><br/>");
for (int nodeCount = 0; nodeCount < xDoc.ChildNodes.Count; nodeCount++)
{
Response.Write(xDoc.ChildNodes[nodeCount].Name + ":");
Response.Write(xDoc.ChildNodes[nodeCount].InnerXml + "<br/>");
}
Response.Write("</p>");
.. and the output I get in the aspx page is as follows:
First Result
xml:
Response:OK122.160.37.198ININDIAWEST BENGALKOLKATA70015522.569788.3697+05:30
I want the values 'WEST BENGAL' and 'KOLKATA' from it. I am not being able to read/write this in xml format so that I can grab the required nodes and their values. How to do that?
You can use XPath to search the XML. use your "xDoc" variable
XPathDocument doc = new XPathDocument(XmlReader(xDoc));
XPathNavigator nav = doc.CreateNavigator();
XPathExpression exprName = nav.Compile(xPathName);
XPathNodeIterator iteratorName = nav.Select(exprName)
You could use the Descendants() function on the XDocument itself, consider this example:
(Note - have made assumptions about how your data looks)
using System.Xml.Linq;
static void Main()
{
var xml = "<Data><ININDIA>WEST BENGAL</ININDIA><ININDIA>KOLKATA</ININDIA></Data>";
var xd = XDocument.Parse(xml);
//get all `XElement` objects with the name "ININDIA"
foreach (var e in xd.Root.Descendants()
.Where(e=>e.Name.LocalName=="ININDIA"))
{
Console.WriteLine(e.Value);
}
}
will produce
WEST BENGAL
KOLKATA

Getting sibling using xPath

I am currently working on a .net C# solution that returns 2 sibling nodes. Using Xpath 1.0
A small example of my xml doc is this:
<PLAY>
<SCENE>
<SPEAKER>
</SPEAKER>
<LINE>
</LINE>
</SCENE>
</PLAY>
I am using the following code to get the line and the speaker but i dont know why i get the entire xml doc being passed in instead of just the sibling (speaker)
I have :
List speakers = new List();
XmlDocument myDoc = new XmlDocument();
myDoc.Load(textXMLFile.Text.ToString());
// Clear the text box...
textResults.Text = "";
// ADD THIS...
XPathNavigator theNav = myDoc.CreateNavigator();
XPathNavigator theNav2 = myDoc.CreateNavigator();
//XmlNodeList theNodes =
// myDoc.SelectNodes(textXPath.Text.ToString());
textXPath.Text = "//SPEECH/LINE";
string val = "//SPEECH/SPEAKER";
XPathNodeIterator theNodes = theNav.Select(textXPath.Text.ToString());
XPathNodeIterator theNodes2 = theNav2.Select(val);
StringBuilder output = new StringBuilder();
while (theNodes.MoveNext())
{
if (theNodes.Current.InnerXml.ToString() == "Upon my sword.")
{
break;
}
else
{
speakers.Add(theNodes2.Current.InnerXml.ToString());
speakers.Add(theNodes2.Current.InnerXml.ToString());
}
}
for (int i =0; i < speakers.Count; ++i)
{
output.Append (speakers[i]+" ");
}
MessageBox.Show(""+output);
theNodes.Current.InnerXml.ToString() works fine for returning the line but theNodes2.Current.InnerXml.ToString() seems to return the entire XML instead of the speaker.
Any comments or suggestions are appreciated.
After staring at this for awhile i totally missed that i needed to move theNodes2 also in the while loop like so
while(theNodes2.MoveNext())
Thanks All
//SPEECH/LINE is not going to find anything in a document where the elements are named "play", "scene", "speaker", and "line". Please try to be more careful in formulating your questions. Downvoting.

Categories

Resources