Checking if element exists in XML file - c#

I need to check if an element in XML file exists. After searching here, I have tried a code from one of very similiar questions I found here, so the code looks like this(it is looped using foreach so it checks every airport in group airports):
string icao = airport.Attributes.GetNamedItem("icao").Value;
if(airports.SelectSingleNode("/vEsup/airports/airport/" + icao + "/departures")==null)
{
MessageBox.Show("I exist!");
}
Please note that the message box is just for testing, I find it the easiest way to check if the code is working properly. However, I found out that whatever path I enter, it always shows the messagebox, regardless if it exist in the XML file or not.

You can use Linq to query specific xml nodes and attributes also.
Here is link to similar sample:
http://www.codearsenal.net/2012/07/c-sharp-load-xml-using-xlinq.html

"shows the messagebox if it exist in the XML file or not." seems to be incorrect as you checking for node not to be present in XML if (a.SelectSingleNode(...)==null).
Most likely you need to correctly specify namespaces to you nodes. (need sample XML to give any better suggestion)

In your 'if' block, aren't you checking to see IF the string is null?
My guess - and I could be wrong here - is that you meant:
string icao = airport.Attributes.GetNamedItem("icao").Value;
if(airports.SelectSingleNode("/vEsup/airports/airport/" + icao + "/departures")!=null)
{
return true;
}
MessageBox.Show("I exist!");

Related

Get partcular information from text file (C#)

I need a c# program which can split strings and copy some particular informations into another file.
I've a text file like this:
BRIDGE.V2014R6I1.SOFT
icem.V4R12I2.SOFT
mygale.V4R1I1.SOFT,patch01_MAJ_APL.exe
photoshop.V2014R10I1.SOFT
rhino.V5R0I1.SOFT,patch01_Update_Files.exe
TSFX.V2R3I2.SOFT,patch01_corrections.exe,patch02_clock.exe,patch03_correction_tri_date.exe,patch04_gestion_chemins_unc.exe
and I need only some of these information into another file as below :
BRIDGE,SOFT
ICEM,SOFT
MYGALE,SOFT
PHOTOSHOP,SOFT
any helps pls :)
As I don't know, wether your text file is always like that, I can only provide a specific answer. First of all you have to, as ThatsEli pointed out, split the string at the point:
var splitted = inputString.Split(".");
Now it seems as though your second (zero based index) item has the irrelevant information with a comma splitted from the relevant. So all you have to do is to build together the zeroth and the second, while the second only has the first part before the comma:
var res = $"{splitted[0]},{splitted[2].Split(",")[0]}";
However, you seem to want your result in uppercase:
var resUpper = res.ToUpper();
But actually this only works as long as you have a perfect input file - otherwise you have to check, wether it actually has that many items or you'll get an IndexOutOfRange exception.
Actually I'm not sure wether you know how to read/write from/to a file, so I'll provide examples on this as well.
Read
var path = #"Your\Path\To\The\Input\File";
if (!File.Exists(path))
{
Console.WriteLine("File doesn't exist! If you're using a console, otherwise use another way to print error messages");
return;
}
var inputString = File.ReadAllText(path);
Write
var outputPath = #"your\Output\Path";
if(!File.Exists(outputPath))
{
Console.WriteLine("You know what to put here");
return;
}
File.WriteAllText(outputPath, inputString);
I would split the string and create a new file with parts of the array you got from the split.
You can split a string with eg. Split(".");
And then e.g. create a new string stringname = splitstring[0] + "," + splitstring[2]
That would add the first and third part back together.
That would apply to your first line.

Parsing Resx file with C# crashes on relative paths

Out of the sheer frustration of having to copy resx data into word to get the word count
i've started to write my own tool to do so.
Well that made me run into an issue.
i have icons and such things in the Resources.resx file.
and they have relative paths according to the project they are being used int.
Which they should have obviously.
Well when i try to parse the Resx file in another application to count the words from the Value column.
i am getting errors as they can't parse the relative path. they end up going to folders that do not exist in my wordcount application.
Does any of you have an idea how i can fool the app into looking in the right folder when parsing these values?
i'm not quite sure why it is parsing those values to begin with.
it should just grab the string that's all i care about.
i'm using the ResXReader
ResXResourceReader reader = new ResXResourceReader(filename);
foreach(System.Collections.DictionaryEntry de in reader)
{
if (((string)de.Key).EndsWith(".Text"))
{
System.Diagnostics.Debug.WriteLine(string.Format("{0}: {1}", de.Key, de.Value));
}
}
I found this here: Word Count of .resx files
It errors out on the foreach.
..\common\app.ico for example.
anyone have an idea on how to do this?
Alright.
So the solution was a little easier than expected.
i was using an outdated Class.
I should have been using XDocument instead of XmlDataDocument
secondly LINQ is the bomb.
all i had to do was this:
try
{
XDocument xDoc = XDocument.Load(resxFile);
var result = from item in xDoc.Descendants("data")
select new
{
Name = item.Attribute("name").Value,
Value = item.Element("value").Value
};
resxGrid.DataSource = result.ToArray();
}
and you can even allow empty strings if you cast those attributes/elements to (String)
Hope this helps someone!
Try to use ResXResourceReader for this purpose - see http://msdn.microsoft.com/en-us/library/czdde9sc.aspx

Returning the first possible node's inner text in a XML file

I wrote a method that specificly searches for a given full xpath and returns the inner text. But since the files I am working on all have unique node names, I want to do it somehow that only passing the node name do the job.
How my code looks like at the moment:
public string FileInfo(string info)
{
switch (info)
{
//FileInfo
case "fileCreator":
fileCreator = ztr.SelectSingleNode("//Document/FileInfo/Creator").InnerText;
return fileCreator;
case "fileName":
fileName = ztr.SelectSingleNode("//Document/FileInfo/Name").InnerText;
return fileName;
//And so on with lots of other cases!!!
How can I make it somehhow that it searches for the first occurance of info string that is a xml node so I dont have to be stupid and write all these switch statements...
UPDATE
please note not all the stuff I want are located in FileInfo node...I want the method to search for the node I pass to it! Or better to say I want to pass the name of the node itself into this method and get its value. Sorry if I was confusing prior to this edit!
some more examples in the xml file:
/Document/RuntimeInfo/Operator
So I want to pass in "Operator" into my method and I get its value! should be up to the method to discover the correct path. the pats are unique so it wouldnt be a bad idea to implement this method.
won't this do the job?
var value = ztr.SelectSingleNode(string.Format("//{0}", info).InnerText;
return ztr.SelectSingleNode(string.Format("//Document/FileInfo/{0}",
info.Replace("file", "").InnerText;
EDIT
if the searched node is always at the same nesting level, you could probably use a wild card
return ztr.SelectSingleNode(string.Format("//Document/*/{0}",
info).InnerText;
By the way, in your example, you pass fileCreator to find the Creator Node. Typo ?
Try,
return ztr.SelectSingleNode(string.Format("//{0}[contains(name(..),'Info')]", info));
If info is Operator it will return the first Operator node that has a parent node with Info in its name.
Use this XPath:
//Document/FileInfo/[0]
and your code can be like this:
public string FileInfo(string info)
{
return ztr.SelectSingleNode("//Document/FileInfo/[0]").InnerText;
}
See more about xpath here.

XML DocumentWriter - Stop empty elements appearing over two lines in .NET

I am using the XML document object in VB.NET to manipulate XML.
My application creates a new XML fragment and updates the XML via the innerXML method:
reasonFrag.InnerXml = String.Format("<ReasonForPayment>{0}</ReasonForPayment>", reason)
This produces the correct XML output on most occasions, e.g.
<ReasonForPayment>reason</ReasonForPayment>
If the reason string is empty I get element spanning two lines in the XML as follows:
<ReasonForPayment>
</ReasonForPayment>
I am looking for a way of keeping the element on a single line while maintaining the same format, e.g.
<ReasonForPayment></ReasonForPayment>
The alternative <ReasonForPayment /> is not acceptable (third party application wont accept it).
Thanks
Steven
I think the best way to handle this would be to do something like this:
if (reason == null | reason.Trim() == "")
{
reasonFrag.IsEmpty = true;
}
else
{
reasonFrag.InnerText = reason.Trim();
}
This changes the output to
<ReasonForPayment/>
if(string.IsNullOrEmpty(reason))
{
reasonFrag.InnerXml = "<ReasonForPayment></ReasonForPayment>"
}
else
{
reasonFrag.InnerXml = String.Format("<ReasonForPayment>{0}</ReasonForPayment>", reason)
}
Not tested but maybe something like
edit threw it into LinqPad, works just fine for what you need.
public static string ToXmlFragment(this object input, string element)
{
//extension method, place in a static class somewhere
return string.IsNullOrEmpty(input.ToString()) ?
string.Format("<{0}></{0}>",element) :
string.Format("<{0}>{1}</{0}>",element,input);
}
reasonFrag.InnerXml = reason.ToXmlFragment("ReasonForPayment");
The solution to my problem was unusual. When reading or writing files in .NET using streamreader/writer, textreader/writer and the XMLDocument object, the document format changes depending on the file extension. So for example reading a file with a XML extension, the file is treated and formatted as XML. This was causing my original problem, a empty element was output over two lines with a CRLF inserted. The solution was to output the steam to a file with a .txt extension and then rename the file to XML, then my formatting was preserved.

XML document - Object reference not set to an instance of an object

I'm working on a website where I need a google map to display the positions of the members of the site.
However, i'm having a bit of trouble getting data from the returned XML document when using the HTTP Geocode Service. When I put the string into the browser it returns the XML just fine and if I set a textbox.Text to the documents InnerText it also displays as it should. But when I want to extract values from nodes, it says object reference not set to an instance of an object.
I'm doing it this way:
string address = m.getProperty("adresse").Value.ToString();
string zip = m.getProperty("postNummer").Value.ToString();
string city = m.getProperty("by").Value.ToString();
XmlDocument doc = new XmlDocument();
doc.Load("http://maps.googleapis.com/maps/api/geocode/xml?address=" + zip + "+" + city + "+" + address + "+DK&sensor=true");
XmlNode latNode = doc.SelectSingleNode("GeoCodeResponse/result/geometry/location/lat/text()");
XmlNode lonNode = doc.SelectSingleNode("GeoCodeResponse/result/geometry/location/lng/text()");
// The error occurs when the code hits these:
string lat = latNode.Value;
string lon = lonNode.Value;
I must admin that I haven't worked that much with XML in C# yet, so any hint will be greatly appreciated! :-) Should also say that the above code is in a foreach loop, looping through the members of the site.
Thanks a lot in advance!
All the best,
Bo
Edit: Sorry, I forgot to paste how I get the values! ;)
Replace "GeoCodeResponse" with "GeocodeResponse"
Please note the capital C in Code is incorrect. Xml is case sensitive.
How did you get latNode and lonNode ? It seems to be those that are null.
Since you are doing it in a loop, does any of the members succeed ? Perhaps you are not getting a hit for some of the addresses, so the lat/long nodes in the document might not be there ?
There really is no way to tell the exact problem from the code you posted. Use your debugger, and step through the code to see why you are not getting latNode assigned.
Edit
This works:
XmlNode latNode = doc.SelectSingleNode("GeocodeResponse/result/geometry/location/lat/text()");
XmlNode lonNode = doc.SelectSingleNode("GeocodeResponse/result/geometry/location/lng/text()");
You had a little type in the path. "code" in "GeocodeResponse" should be lowercase. XPath is case sensitive.

Categories

Resources