How do i read xml file on dropbox with XmlTextReader - c#

I am trying to make my winform application read an xml file stored on dropbox. But when it gets to
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "updater"))
Then it wont continue. but if i remove && (reader.Name == "updater") then it continues but it still dont read the value of "version" and "url".
Link to update.xml: https://www.dropbox.com/s/25gcpllsqsj1qrq/update.xml
Below is my C# code in my project. I am trying to read the update.xml on dropbox with XmlTextReader, but i just never get any of the values back!
I tryed to place messageboxes to show me reader.Name, but it returns "html" instead of "updater".
It dont necessary have to be XmlTextReader. As long as the solution works, then its fine :D
Any help will be appreciated.
private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
{
Version newVersion = null;
string url = "";
XmlTextReader reader = null;
try
{
string xmlURL = "https://www.dropbox.com/s/25gcpllsqsj1qrq/update.xml";
reader = new XmlTextReader(xmlURL);
reader.MoveToContent();
string elementName = "";
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "updater"))
{
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element) elementName = reader.Name;
else
{
if ((reader.NodeType == XmlNodeType.Text) && (reader.HasValue))
{
switch (elementName)
{
case "version":
newVersion = new Version(reader.Value);
break;
case "url":
url = reader.Value;
break;
}
}
}
}
}
}
catch (Exception)
{
}
finally
{
if (reader != null) reader.Close();
}
Version curVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
if (curVersion.CompareTo(newVersion) < 0)
{
string title = "New version detected.";
string question = "Download the new version?";
if (DialogResult.Yes == MessageBox.Show(this, question, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
System.Diagnostics.Process.Start(url);
}
}
else
{
MessageBox.Show("The program is up to date!");
}
}

Well, going to the Url provided doesn't give you the XML file as you might expect, it's actually giving you the content through a Dropbox wrapper. So when you're doing your read, you're actually hitting the HTML page. You can double-check this by putting a break point on the elementName for each iteration.
This is the correct URL https://dl.dropboxusercontent.com/s/25gcpllsqsj1qrq/update.xml?token_hash=AAFnI4T9nSCGeVgDKLm7YB79dbjNtoYkAj_mChxVDZL0AQ&dl=1 (got it from the Download button), here give this a try:
string xmlURL = "https://dl.dropboxusercontent.com/s/25gcpllsqsj1qrq/update.xml?token_hash=AAFnI4T9nSCGeVgDKLm7YB79dbjNtoYkAj_mChxVDZL0AQ&dl=1";
This is an alternative way to load the contents to a XDocument and further query it with LINQ:
string url = "https://dl.dropboxusercontent.com/s/25gcpllsqsj1qrq/update.xml?token_hash=AAFnI4T9nSCGeVgDKLm7YB79dbjNtoYkAj_mChxVDZL0AQ&dl=1";
WebRequest request = HttpWebRequest.Create(url);
using (WebResponse response = request.GetResponse())
using (Stream stream = response.GetResponseStream())
{
var doc = XDocument.Load(stream);
// do your magic (now it's a valid XDocument)
}

Related

How to retrieve all Elements from XML file using c#

I am trying to retrieve all elements from an XML file, but I just can reach one, is there any way I can retrieve all?
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (XmlReader reader = XmlReader.Create(new StreamReader(objResponse.GetResponseStream())))
{
while (reader.Read())
{
#region Get Credit Score
//if (reader.ReadToDescendant("results"))
if (reader.ReadToDescendant("ssnMatchIndicator"))
{
string ssnMatchIndicator = reader.Value;
}
if (reader.ReadToDescendant("fileHitIndicator"))
{
reader.Read();//this moves reader to next node which is text
result = reader.Value; //this might give value than
Res.Response = true;
Res.SocialSecurityScore = result.ToString();
//break;
}
else
{
Res.Response = false;
Res.SocialSecurityScore = "Your credit score might not be available. Please contact support";
}
#endregion
#region Get fileHitIndicator
if (reader.ReadToDescendant("fileHitIndicator"))
{
reader.Read();
Res.fileHitIndicator = reader.Value;
//break;
}
#endregion
}
}
Can somebody help me out with this issue?
I am also using objResponse.GetResponseStream() because the XML comes from a response from server.
Thanks a lot in advance.
Try this :
XmlDataDocument xmldoc = new XmlDataDocument();
XmlNodeList xmlnode ;
int i = 0;
string str = null;
FileStream fs = new FileStream("product.xml", FileMode.Open, FileAccess.Read);
xmldoc.Load(fs);
xmlnode = xmldoc.GetElementsByTagName("Product");
for (i = 0; i <= xmlnode.Count - 1; i++)
{
xmlnode[i].ChildNodes.Item(0).InnerText.Trim();
str = xmlnode[i].ChildNodes.Item(0).InnerText.Trim() + " " + xmlnode[i].ChildNodes.Item(1).InnerText.Trim() + " " + xmlnode[i].ChildNodes.Item(2).InnerText.Trim();
MessageBox.Show (str);
}
I don't know why what you're doing is not working, but I wouldn't use that method. I've found the following to work well. Whether you're getting the xml from a stream, just put it into a string and bang...
StreamReader reader = new StreamReader(sourcepath);
string xml = reader.ReadToEnd();
reader.Close();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNodeList list = doc.GetElementsByTagName("*");
foreach (XmlNode nd in list)
{
switch (nd.Name)
{
case "ContactID":
var ContactIdent = nd.InnerText;
break;
case "ContactName":
var ContactName = nd.InnerText;
break;
}
}
To capture what is between the Xml tags, if there are no child Xml tags, use the InnerText property, e.g. XmlNode.InnerText. To capture what is between the quotes in the nodes' attributes, use XmlAttribute.Value.
As for iterating through the attributes, if one of your nodes has attributes, such as the elements "Name", "SpectralType" and "Orbit" in the Xml here:
<System>
<Star Name="Epsilon Eridani" SpectralType="K2v">
<Planets>
<Planet Orbit="1">Bill</Planet>
<Planet Orbit="2">Moira</Planet>
</Planets>
</Star>
</System>
Detect them using the Attributes property, and iterate through them as shown:
if (nd.Attributes.Count > 0)
{
XmlAttributeCollection coll = nd.Attributes;
foreach (XmlAttribute cn in coll)
{
switch (cn.Name)
{
case "Name":
thisStar.Name = cn.Value;
break;
case "SpectralType":
thisStar.SpectralClass = cn.Value;
break;
}
}
}
You might find some more useful information HERE.

Read Large XML file using XPath

I am trying to read windows update package.xml file which is roughly 65mb in size, I am trying to just grab the URL attribute using Xpath but for some odd reason my object always returns empty. Here is my code:
doc.Load(#".\package.xml");
string xpath= "/OfflineSyncPackage/FileLocations/FileLocation/#Url";
XmlNodeList nodeList2 = doc.SelectNodes(xpath);
I have also tried using XmlReader which is also not working for me:
string packXML = #".\package.xml";
using (XmlReader xr = XmlReader.Create(packXML))
{
while (xr.Read())
{
switch (xr.NodeType)
{
case XmlNodeType.Element:
if (xr.Name == "OfflineSyncPackage")
{
xr.ReadStartElement("FileLocations");
if (xr.Name == "FileLocations")
{
if (xr.Name == "FileLocation")
{
}
}
}
break;
}
}
}
The package.xml file can be found in package.cab which is in this file: http://download.windowsupdate.com/microsoftupdate/v6/wsusscan/wsusscn2.cab
What is the best way to do this as I do not want to load whole file into memory due to size
Any advice is appreciated! Thank you
I figured this out finally!
public void ParseXML(string XMLPath)
{
XmlReader xmlReader = XmlReader.Create(XMLPath);
while (xmlReader.Read())
{
if (xmlReader.Name.Equals("FileLocation") && (xmlReader.NodeType == XmlNodeType.Element))
{
string url = xmlReader.GetAttribute("Url");
}
}
}

System.IO exception coming while saving XML document in C#

After importing plenty of XML files into application i tried to do modifications on it by using XML document class, for this i created few methods to do modifications.
The thing is the starting method it's working fine and when comes to the second one it's displaying System.IO exception like "File is already using another process".
So any one help me out how can i solve this issue.
Sample code what i'm doing:
Method1(fileList);
Method2(fileList);
Method3(fileList);
private void Method1(IList<RenamedImportedFileInfo> fileList)
{
try
{
string isDefaultAttribute = Resource.Resources.ImportIsDefaultAttribute;
string editorsPath = editorsFolderName + Path.DirectorySeparatorChar + meterType;
string profilesPath = profileFolderName + Path.DirectorySeparatorChar + meterType;
string strUriAttribute = Resource.Resources.ImportUriAttribute;
foreach (RenamedImportedFileInfo renameInfo in fileList)
{
if (renameInfo.NewFilePath.ToString().Contains(editorsPath) && (renameInfo.IsProfileRenamed != true))
{
var xmldoc = new XmlDocument();
xmldoc.Load(renameInfo.NewFilePath);
if (xmldoc.DocumentElement.HasAttribute(isDefaultAttribute))
{
xmldoc.DocumentElement.Attributes[isDefaultAttribute].Value = Resource.Resources.ImportFalse;
}
XmlNodeList profileNodes = xmldoc.DocumentElement.GetElementsByTagName(Resource.Resources.ImportMeasurementProfileElement);
if (profileNodes.Count == 0)
{
profileNodes = xmldoc.DocumentElement.GetElementsByTagName(Resource.Resources.ImportBsMeasurementProfileElement);
}
if (profileNodes.Count > 0)
{
foreach (RenamedImportedFileInfo profileName in oRenamedImportedFileList)
{
if (profileName.NewFilePath.ToString().Contains(profilesPath))
{
if (string.Compare(Path.GetFileName(profileName.OldFilePath), Convert.ToString(profileNodes[0].Attributes[strUriAttribute].Value, CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase) == 0)
{
profileNodes[0].Attributes[strUriAttribute].Value = Path.GetFileName(profileName.NewFilePath);
renameInfo.IsProfileRenamed = true;
break;
}
}
}
}
xmldoc.Save(renameInfo.NewFilePath);
xmldoc = null;
profileNodes = null;
}
}
oRenamedImportedFileList = null;
}
catch (NullReferenceException nullException) { LastErrorMessage = nullException.Message; }
}
Thanks,
Raj
You are probably opening the same file twice in your application. Before you can open it again, you have to close it (or leave it open and work on the same document without opening it again).
For help on how to implement this, please show us more code so we can give you advice.

View all text of an element with XmlReader C#

I'm using an XmlReader to iterate through some XML. Some of the XML is actually HTML and I want to get the text content from the node.
Example XML:
<?xml version="1.0" encoding="UTF-8"?>
<data>
<p>Here is some <b>data</b></p>
</data>
Example code:
using (XmlReader reader = new XmlReader(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
// I want to get all the TEXT contents from the this node
myVar = reader.Value;
}
}
}
This doesn't get me all the contents. How do I get all the contents from the node in that situation?
Use ReadInnerXml:
StringReader myUrl = new StringReader(#"<?xml version=""1.0"" encoding=""UTF-8""?>
<data>
<p>Here is some <b>data</b></p>
</data>");
using (XmlReader reader = XmlReader.Create(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
// I want to get all the TEXT contents from the this node
Console.WriteLine(reader.ReadInnerXml());
}
}
}
Or if you want to skip the <b> as well, you can use an aux reader for the subtree, and only read the text nodes:
StringReader myUrl = new StringReader(#"<?xml version=""1.0"" encoding=""UTF-8""?>
<data>
<p>Here is some <b>data</b></p>
</data>");
StringBuilder myVar = new StringBuilder();
using (XmlReader reader = XmlReader.Create(myUrl))
{
while (reader.Read())
{
if (reader.Name == "p")
{
XmlReader pReader = reader.ReadSubtree();
while (pReader.Read())
{
if (pReader.NodeType == XmlNodeType.Text)
{
myVar.Append(pReader.Value);
}
}
}
}
}
Console.WriteLine(myVar.ToString());
I can't upvote or comment on others' responses, so let me just say carlosfigueira hit the nail on the head, that's exactly how you read the text value of an element. his answer helped me immensely.
for the sake of exmeplification here's my code:
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
{
if (reader.Name == "CharCode")
{
switch (reader.ReadInnerXml())
{
case "EUR":
{
reader.ReadToNextSibling("Value");
label4.Text = reader.ReadInnerXml();
}
break;
case "USD":
{
reader.ReadToNextSibling("Value");
label3.Text = reader.ReadInnerXml();
}
break;
case "RUB":
{
reader.ReadToNextSibling("Value");
label5.Text = reader.ReadInnerXml();
}
break;
case "RON":
{
reader.ReadToNextSibling("Value");
label6.Text = reader.ReadInnerXml();
}
break;
}
}
}
break;
}
}
the file I'm reading can be found here: http://www.bnm.md/md/official_exchange_rates?get_xml=1&date=
(you have to add a date in DD.MM.YYYY format to it to get the .XML)
I suggest you use HtmlAgilityPack which is a mature and, stable library for doing this sort of thing. It takes care of fetching the html, converting it to xml, and allows you to select the nodes you'd like with XPATH.
In your case it would be as simple as executing
HtmlDocument doc = new HtmlWeb().Load(myUrl);
string text = doc.DocumentNode.SelectSingleNode("/data/p").InnerText;

Search line in *.CSV-

I can't belive, the easiest task won't work!
I just want to loop through a csv file by using the StreamReader-Class and find a key in a associative line.
e.g.:
key1;value1
key2;value2
key3;value3
If the key exists, no problems. Otherwise EOF should be reached, but it does not work!
If I discard the buffered data, EOF will be reached everytime. In result no key will be found.
Edit: with all the suggestions, but same result!
StreamReader reader = null;
if(!string.IsNullOrEmpty(textBox1.Text))
{
try
{
reader = new StreamReader(#"ident.csv", Encoding.ASCII);
string buffer;
string[] str = null;
while((buffer = reader.ReadLine()) != null)
{
if(buffer.Contains(";"))
{
str = buffer.Split(';');
if(str[0].Equals(textBox1.Text))
break;
}
}
if(reader == null)
{
MessageBox.Show("Ident not found!");
textBox2.Text = "";
}
else
{
textBox2.Text = str[1];
Clipboard.SetText(str[1]);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
reader.Dispose();
reader.Close();
}
}
else
{
MessageBox.Show("Set ident!");
}
}
very strange, this works on my pc:
static void Main(string[] args)
{
string buffer = string.Empty;
StreamReader reader = new StreamReader(#"e:\a.csv");
do
{
buffer = reader.ReadLine();
if (buffer.Contains(";"))
{
string[] str = buffer.Split(';');
if (str[0] == "1")
{
Console.WriteLine("ok");
break;
}
}
}
while (!reader.EndOfStream);
}
csv contains:
1;2;3;4;5;
sdfsdf;sdfsdfcv;aasd;
As Konerak points out in his comment, use .equals() to compare Strings.
It just happens that "1" == "1" AND "1".equals("1") both are true but it's just a coincidence (that's why the second piece of code works). More on String equality here.
Do not forget:the file coding is the key for read files!
coding:UTF8,ASCII,UTF16,GB2312
Stupid thought but does either ident.csv or your textbox contain any extra spaces?
Try something like if(str[0].Trim().Equals(textBox1.Text.Trim()))

Categories