Selecting random nodes from xml file - c#

My application allows the user to speak into a microphone and the program will talk back to the user. I have responses saved in a XML file and when the user talks, I want the program to check in the XML file and display a random node in the section it should. The following is what my XML file looks like:
<?xml version="1.0" encoding="utf-8" ?>
<MarcusXMLFile xmlns:Responses="http://www.rewardstrike.com/XMLFile1.xml"">
<response>
<posanswer>
<answer>Yes, sir.</answer>
<answer>Right away.</answer>
</posanswer>
</response>
</MarcusXMLFile>
My code for selecting a random node is:
private void Responses()
{
string query = String.Format("http://www.rewardstrike.com/XMLFile1.xml");
XmlDocument Responses = new XmlDocument();
Responses.Load(query);
XmlNode channel = Responses.SelectSingleNode("MarcusXMLFile");
XmlNodeList nodes = Responses.SelectNodes("MarcusXMLFile/response");
try
{
XmlNodeList positiveresponses = Responses.SelectNodes("./posanswer/answer");
foreach (XmlNode ans in positiveresponses.Cast<XmlNode>().OrderBy(elem => Guid.NewGuid()))
{
response = ans.InnerText;
}
QEvent = "positiveresponse";
}
catch { }
}
And my code for calling the event is:
case "Hello":
case "Hello Jarvis":
Responses();
if (QEvent == "positiveresponse")
{
JMARCUS.Speak(response);
}
break;
However, when I speak to the application, it gives me an error saying the text he is supposed to speak in null. Any ideas?

Your second Responses.SelectNodes finds no nodes, so positiveresponses has no nodes, the foreach loop has nothing to iterate on, and response is never assigned a value.
Try changing:
XmlNodeList positiveresponses = Responses.SelectNodes("./posanswer/answer");
To:
XmlNodeList positiveresponses
= Responses.SelectNodes("MarcusXMLFile/response/posanswer/answer");

Related

How do I remove empty tags from xml file using c#

I have created a program in C# which adds and deletes data in an XML file.
Adding new data works totally fine, however on deleting the data, data gets deleted but empty tags still remain in the xml file.
How do I remove them? please help
The code is as follows:
private void deleteall_Click(object sender, EventArgs e) // delete single record button
{
XmlDocument xdata = new XmlDocument();
XmlNode xnode = xdata.SelectSingleNode("Information/Database");
xdata.Load("C:\\Users\\son14344\\Documents\\Visual Studio 2010\\Projects\\project.xml");
XmlNodeList oNodeList;
oNodeList = xdata.SelectNodes("Information/Database");
string s;
s = Convert.ToString(textBox1.Text);
try
{
foreach (XmlElement Oelement in oNodeList)
{
if (Oelement.SelectSingleNode("Database_Name").InnerText == s)
{
//Oelement.ParentNode.RemoveChild(Oelement);
Oelement.RemoveAll();
}
xdata.Save("C:\\Users\\son14344\\Documents\\Visual Studio 2010\\Projects\\project.xml");
//}
}
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
Try
Oelement.ParentNode.RemoveChild(Oelement);
instead of
Oelement.RemoveAll();
You have to capture the node that meets your condition.
Inside your if condition
XmlNode node = Oelement.SelectSingleNode("Database_Name");
XmlNode parent = node.ParentNode;
// remove the child node
parent.RemoveChild(node);

How to remove unnecessary xmlns attribute in C#?

I'm trying to update an existing XML file, but always when I update it adding new tags the xmlns="" attribute mysteriously appears in all tags and I didn't find a way to remove it.
private static void EditarXML(string path, List<SiteUrl> listaUrls, bool indice, string loc)
{
XmlDocument documentoXML = new XmlDocument();
documentoXML.Load(path);
XmlNode sitemap = documentoXML.CreateElement("sitemap");
XmlNode xloc = documentoXML.CreateElement("loc");
xloc.InnerText = loc;
sitemap.AppendChild(xloc);
XmlNode lastmod = documentoXML.CreateElement("lastmod");
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
documentoXML.DocumentElement.AppendChild(sitemap);
}
Any help or ideas would be appreciated.
This will happen with the parent node you are appending to has a namespace, but you don't specify it in the CreateElement() call.
To handle this, you can get the namespace from the DocumentElement, like this (my sample just creates the document in memory, but the principle is the same), and pass it to CreateElement().
if (x.DocumentElement != null) {
var xmlns = (x.DocumentElement.NamespaceURI);
var sitemap = x.CreateElement("sitemap", xmlns);
var xloc = x.CreateElement("loc", xmlns);
xloc.InnerText = "Hello";
sitemap.AppendChild(xloc);
var lastmod = x.CreateElement("lastmod", xmlns);
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
x.DocumentElement.AppendChild(sitemap);
}
Console.WriteLine(x.InnerXml);
Output
<test xmlns="jdphenix"><sitemap><loc>Hello</loc><lastmod>4/20/2015</lastmod></sitemap></test>
Note that if I did not pass the parent namespace to each CreateElement() call, the children of that call would have the blank xmlns.
// incorrect - appends xmlns=""
if (x.DocumentElement != null) {
var sitemap = x.CreateElement("sitemap");
var xloc = x.CreateElement("loc");
xloc.InnerText = "Hello";
sitemap.AppendChild(xloc);
var lastmod = x.CreateElement("lastmod");
lastmod.InnerText = DateTime.Now.ToShortDateString();
sitemap.AppendChild(lastmod);
x.DocumentElement.AppendChild(sitemap);
}
Console.WriteLine(x.InnerXml);
Output
<test xmlns="jdphenix"><sitemap xmlns=""><loc>Hello</loc><lastmod>4/20/2015</lastmod></sitemap></test>
Related reading: Why does .NET XML append an xlmns attribute to XmlElements I add to a document? Can I stop it?
How to prevent blank xmlns attributes in output from .NET's XmlDocument?

How to convert XMLDocument type to string in order to show the result in a label

I'm trying to show weather information on my website from world weather online. I'm using VS2012 with c# to create this.
I could able to retrieve data from world weather online to a function under a XMLDocument type variable "WP_XMLdoc".
Take a look at the code below:
public static XmlDocument WeatherAPI(string sLocation)
{
HttpWebRequest WP_Request;
HttpWebResponse WP_Response = null;
XmlDocument WP_XMLdoc = null;
String Value;
string sKey = "xxxxxxxxxxxxxxxxxxxxxxxxx"; //The API key generated by World Weather Online
string sRequestUrl = "http://api.worldweatheronline.com/free/v1/weather.ashx?format=xml&"; //The request URL for XML format
try
{
//Here we are concatenating the parameters
WP_Request = (HttpWebRequest)WebRequest.Create(string.Format(sRequestUrl + "q=" + sLocation + "&key=" + sKey));
WP_Request.UserAgent = #"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4";
//Making the request
WP_Response = (HttpWebResponse)WP_Request.GetResponse();
WP_XMLdoc = new XmlDocument();
//Assigning the response to our XML object
WP_XMLdoc.Load(WP_Response.GetResponseStream());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
WP_Response.Close();
return WP_XMLdoc;
}
}
So, now I just want to take XML data from "WP_XMLdoc" variable and show few details like temp_c, windspeed, time etc in my labels.
How can I do that?
The XML data that rest under "WP_XMLdoc" is given below:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<request>
<type>City</type>
<query>London, United Kingdom</query>
</request>
<current_condition>
<observation_time>04:17 AM</observation_time>
<temp_C>17</temp_C>
<temp_F>63</temp_F>
<weatherCode>143</weatherCode>
<weatherIconUrl>
<![CDATA[http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0006_mist.png]]>
</weatherIconUrl>
<weatherDesc>
<![CDATA[Mist]]>
</weatherDesc>
<windspeedMiles>0</windspeedMiles>
<windspeedKmph>0</windspeedKmph>
<winddirDegree>62</winddirDegree>
<winddir16Point>ENE</winddir16Point>
<precipMM>0.0</precipMM>
<humidity>94</humidity>
<visibility>2</visibility>
<pressure>1010</pressure>
<cloudcover>50</cloudcover>
</current_condition>
<weather>
<date>2014-09-19</date>
<tempMaxC>28</tempMaxC>
<tempMaxF>82</tempMaxF>
<tempMinC>14</tempMinC>
<tempMinF>57</tempMinF>
<windspeedMiles>5</windspeedMiles>
<windspeedKmph>8</windspeedKmph>
<winddirection>SSE</winddirection>
<winddir16Point>SSE</winddir16Point>
<winddirDegree>149</winddirDegree>
<weatherCode>356</weatherCode>
<weatherIconUrl>
<![CDATA[http://cdn.worldweatheronline.net/images/wsymbols01_png_64/wsymbol_0010_heavy_rain_showers.png]]>
</weatherIconUrl>
<weatherDesc>
<![CDATA[Moderate or heavy rain shower]]>
</weatherDesc>
<precipMM>8.3</precipMM>
</weather>
</data>
Please help!
Assuming that your existing code successfully load the XML data to XmlDocument object, we can then use SelectSingleNode() passing suitable XPath expression as argument to get any particular part of the XML document. For example, to get <temp_C> value :
string temp_c = WP_XMLdoc.SelectSingleNode("/data/current_condition/temp_C")
.InnerText;
Another option is using newer XML API, XDocument. It has Load() method which functionality is similar to XmlDocument.Load() :
XDocument WP_XMLdoc = XDocument.Load(WP_Response.GetResponseStream());
Using this approach, we can simply cast XElement to string to get it's value :
string temp_c = (string)WP_XMLdoc.XPathSelectElement("/data/current_condition/temp_C");
Try something like this, as an example:
var str = #"<your xml here>";
XDocument xdoc = XDocument.Parse(str);
var output = new List<string>();
foreach (var element in xdoc.Element("data").Element("current_condition").Elements())
{
output.Add(string.Format("{0} : {1}",element.Name, element.Value.ToString()));
}
This would traverse the properties of the current_condition node, you can adjust as necessary to extract what you need.
Ok, according to your answer in comments I believe you need to show multiple columns of data.
Best option would be to use a GridView to populate your XML data using ADO.net. It's bit easy.
Have a look at this SO thread

Parsing XML in a foreach loop

I am making a Application on Windows Phone 8. The bit I am struggling with is getting the XML parsed.
Here the XML File:
<ArrayOfThemeParkList xmlns="http://schemas.datacontract.org/2004/07/WCFServiceWebRole1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ThemeParkList>
<id>1</id>
<name>Alton Towers</name>
</ThemeParkList>
<ThemeParkList>
<id>2</id>
<name>Thorpe Park</name>
</ThemeParkList>
<ThemeParkList>
<id>3</id>
<name>Chessington World Of Adventures</name>
</ThemeParkList>
<ThemeParkList>
<id>4</id>
<name>Blackpool Pleasure beach</name>
</ThemeParkList>
</ArrayOfThemeParkList>
And the c# code that tries to parse it is:
void ThemeParksNames_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
//Now need to get that data and display it on the page
//check for errors
if (e.Error == null)
{
//No errors have been passed now need to take this file and parse it
//Its in XML format
XDocument xdox = XDocument.Parse(e.Result);
//need a list for them to be put in to
List<ThemeParksClass> ParkList = new List<ThemeParksClass>();
//Now need to get every element and add it to the list
foreach (XElement item in xdox.Root.Elements("ThemeParkList"))
{
ThemeParksClass content = new ThemeParksClass();
content.ID = Convert.ToInt32(item.Element("id").Value);
content.ThemeParkName = item.Element("name").Value.ToString();
ParkList.Add(content);
}
parkList.ItemsSource = ParkList.ToList();
}
else
{
//There an Error
}
}
Now when using Break points it get to the for each loop but does not run at all just moves on. I am guessing i have the for each loop set wrong.
Many Thanks.
Your ThemeParkList elements are in a namespace http://schemas.datacontract.org/2004/07/WCFServiceWebRole1 - you'll need to adjust accordingly:
XNamespace ns = "http://schemas.datacontract.org/2004/07/WCFServiceWebRole1";
foreach (XElement item in xdox.Descendants(ns + "ThemeParkList"))
You'll need to handle the other elements in the same way.

Saving Particular Node in XML File

I am populating textboxes with information from a particular node based on it's ConfirmNum. Then when all info is updated, I am saving information (by a submit button) back to the particular node.
However, upon saving, every node in the XML file that was empty drops down to another line.
Example XML Before Save:
<OnlineBanking>
<Transactions>
<Txn>
<Login></Login>
<UserName>userName</UserName>
<CustomerName>CustomerName</CustomerName>
<ConfirmNum>1234</ConfirmNum>
</Txn>
</Transactions>
</OnlineBanking>
My code (below) will save the information for that node, based on the Page.aspx?CID=1234 number. However, every node in the entire XML file that was blank, will now have a line break in it. Not just the Txn we just edited, but all.
Here is my code:
protected void btnSubmit_Click(object sender, EventArgs e)
{
XmlDocument item = new XmlDocument();
item.Load(xmlFileName);
if (CID != "")
{
XmlNode xlist = item.SelectSingleNode("OnlineBanking/Transactions/Txn[ConfirmNum=" + CID + "]");
if (xlist != null)
{
xlist.ChildNodes.Item(0).InnerText = tbLogin.Text;
xlist.ChildNodes.Item(1).InnerText = tbUserName.Text;
xlist.ChildNodes.Item(2).InnerText = tbCustomerName.Text;
item.Save(xmlFileName);
}
}
}
Example XML After Save:
<OnlineBanking>
<Transactions>
<Txn>
<Login>
</Login>
<UserName>userName</UserName>
<CustomerName>CustomerName</CustomerName>
<ConfirmNum>1234</ConfirmNum>
</Txn>
</Transactions>
</OnlineBanking>
Note how the <login> is on another line than </login>. This is what I am talking about. Hope someone can see clearly what I am not doing.
Try setting the PreserveWhitespace property to True and see if it will stop inserting line breaks upon calling Save:
XmlDocument item = new XmlDocument();
item.PreserveWhitespace = true;
item.Load(xmlFileName);
One compromise is:
if(string.IsNullOrWhiteSpace(tbLogin.Text))
xlist.ChildNodes.Item(0).IsEmpty = true;
else
xlist.ChildNodes.Item(0).InnerText = tbLogin.Text;
This will give you:
<Login />

Categories