C# XmlTextReader and DataSet causing Duplicate Name Exception - c#

I'm trying to read a standard CNN news feed to put into a table, and it's telling me "duplicate 'link' column exception." on the line:
cnnds.ReadXml(CNNfeed);
Here's the whole code, and it stops the code and throws errors, when it should simply just ignore duplicate columns or use the last column.
XmlTextReader CNNfeed = new XmlTextReader("http://rss.cnn.com/rss/cnn_topstories.rss");
DataSet cnnds = new DataSet("CNN");
cnnds.ReadXml(CNNfeed, XmlReadMode.Auto); // read the XML feed
DataTable CNNNewsFeedTable = new DataTable("CNNNewsFeed");
How do I resolve this issue? I've tried everything, and the only way to get this to work is to properly not use the CNN feed.
I just changed XmlReadMode.ReadSchema and it got through this part but then it says cnnds.Tables[1] is an index out of range. Like as if it's an empty XML.
Is there any easier way to read RSS feeds from other websites without all these exceptions and problems?
Edit: It seems adding a try { } catch() around it, however redundant, seems to bypass this problem.

If you want to read the xml in a dataset, then you need the xml-schema (else ReadXml() can't distinguish between the different namespaces).
Use:
var CNNfeed = new XmlTextReader("http://rss.cnn.com/rss/cnn_topstories.rss");
var cnnds = new DataSet("CNN");
cnnds.ReadXmlSchema("http://www.thearchitect.co.uk/schemas/rss-2_0.xsd"); // read the rss schema
cnnds.ReadXml(CNNfeed); // read the XML feed
But I think you'd better use xpath to find the information you need:
var doc = XDocument.Load("http://rss.cnn.com/rss/cnn_topstories.rss");
foreach (XElement node in (IEnumerable) doc.XPathEvaluate("//item"))
{
Console.WriteLine(node.XPathSelectElement("title").Value);
}

Related

DataSet.ReadXml not getting all data

I have a relatively simple xml file that I would like to use to fill a DataSet. I am trying the following code
using (DataSet ds = new DataSet())
{
ds.ReadXml(Server.MapPath("xmlFileName.xml"));
}
But my dataset ends up with only one row containing the first node of the file.
I have tried other methods such as
XmlReader xmlFile = XmlReader.Create("xmlFileName.xml", new XmlReaderSettings());
DataSet ds = new DataSet();
ds.ReadXml(xmlFile);
And
FileStream fsReadXml = new FileStream("xmlFileName.xml", FileMode.Open);
XmlTextReader xmlReader = new System.Xml.XmlTextReader(fsReadXml);
newDataSet.ReadXml(xmlReader, XmlReadMode.ReadSchema);
Both of which result in empty datasets.
I can't post the entire xml file, but its format is essentially
<service_orders count="70">
<service_order order_number="1111" id="111111">
<customer>
<customer_id>55555</customer_id>
<first_name>John</first_name>
<last_name>Doe</last_name>
<email>JohnDoe#gmail.com</email>
<phone1>55555555</phone1>
The first method I mentioned only generates two columns from this
"service_order_id" and "count"
with values 0 and 70 respectively.
It seems like it's only hitting the first node?
So I'm not sure what I'm doing wrong with these methods. Is the xml file not formatted properly? Do I somehow need to make it go deeper into the nodes? Is there any way I can specify which nodes to hit?
Any help would be appreciated,
Thank you
I realized I had forgotten that DataSets hold multiple tables, and that I was only looking at the first one which contained the root. Though this did help me understand how the parser navigates the xml tree. Only leaf elements (with no children) get added to the tables, all other elements get tables of their own in the dataset.

Appending/Listing LINQ to XML data

I'm currently writing a function to save and read data to/from and XML document through
LINQ. Currently I can write the document just fine, but if I go to add data to an existing item, it simply adds a new item. My goal is to create an address book type system (yes I know there's 1000 out there, it's just a learning project for myself) and I've tried ini and basic text but it seems that XML is the best way to go short of using a local DB like sql. Currently I have:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
var data = new XElement("Entry",
new XElement("Name", textBox1.Text),
new XElement("Address", richTextBox2.Text),
new XElement("Comments", richTextBox1.Text));
doc.Element("Contacts").Add(data);
doc.Save(#"C:\TextXML.xml");
I searched SO and can't seem to find how to append/replace.
Now this saves everything properly, even when I add to the document, but if I want to update an entry I'm not sure how to without creating a new "Entry" nor am have I gotten the knack of removing one. (I'm somewhat new to C# still and self-taught so pardon anything obvious I've overlooked.)
My second issues revolves around loading the information into textboxes.
I'm able to load a list of Entry names into a listbox, but when I go to open the information from that entry I'm not sure how to properly get the nested info.
With the example above I'd need something similar to the following:
XDocument doc = XDocument.Load(#"C:\TextXML.xml");
boxName.Text = The name from the SelectedItem of the list box.
boxAddress.Text = The address child of the element named above etc.
Each method I've tried I wind up with a null reference exception, which tells me I'm not pointing to the right thing, but I'm not sure how to get to those things properly.
I've also tried creating a string and var of the SelectedItem from the list box to help with the naming, and using ToString methods, but still can't figure it out.
For replacing values, there are several functions you can use in XElement:
Value (property with a public setter)
SetValue()
SetElementValue()
SetAttributeValue()
ReplaceWith()
ReplaceNodes()
For example, if you wanted to replace the value in Name:
data.Element("Name").SetValue("NewValue");
or
data.Element("Name").Value = "NewValue";
For loading, once you have the XElement node you desire, then it's as simple as doing
xelement.Value
Or if it's an attribute:
xelement.Attribute("AttributeName").Value
Using your code as an example:
boxName.Text = doc.Element("Entry").Element("Name").Value;
Edit to address comment:
If I'm reading your comment right, you're wanting to extract the Name/Address/etc. data from all the nodes within the Contacts main node?
If so, then you would probably want something like this:
boxName.Text = string.Join(",", doc.Elements("Entry").Select(x => x.Element("Name").Value));
This will give you a single string that has all the names in all Entries separated by a comma. Just change "Name" to "Address" to do the same for addresses.
I'd suggest doing a search for Linq to XML for finding more information about how to use this parsing.

Save datatable as user setting

I currently try to save a datatable as a user setting using die old "properties.settings.default.save()" method.
It does not work. My Settings don't get saved. however it does work when I try to save a string as setting.
So I am really wondering why it doesn't work with the datatable. Saving the datatale would make a lot of things easier for me, so any help on that or any alternative solutions would be greatly appreciated!
You can save the DataTable as an XML string to an ordinary String setting, like this:
StringWriter writer = new StringWriter();
table.WriteXml(writer);
Settings.Default.TableXml = writer.ToString();
You can then load it from the setting like this:
StringReader reader = new StringReader(Settings.Default.TableXml);
table.ReadXml(reader);
I believe I encountered this same problem while performing a LINQ query on a DataTable from an ERP database. After using the CopyToDataTable() method on the query result and assigning it to the settingTable setting, I verified that neither the resultTable nor the settingTable were null and I ran the Settings.Default.Save() method. However, I received a null error when I subsequently attempted to assign the settingTable to a dataTable variable.
I resolved this problem by assigning the settingTable.TableName property to something other than its default value (the null string) before running the Settings.Default.Save() method.
Note: The ERP system is really slow, I would just query the data directly using the ERP's business objects.
sadly the solution above doesn't work for me (got an exceptation that the root element is missing).
I had to make this adjustments.
Create XML String:
StringWriter writer = new StringWriter();
table.WriteXml(writer, XmlWriteMode.WriteSchema); //WriteSchema
Settings.Default.TableXml = writer.ToString();
Create DataTable from Xml String
StringReader reader = new StringReader(Settings.Default.TableXml);
table.ReadXml(reader);
Hope this helps al further users having the same problem ;)

Is there a way to take an XmlNode and display its data in a datagrid view?

I have spent about half a day searching for an answer to this question and am slowly becoming frustrated. I am working with a Web service that returns an XmlNode as its response. I would like to be able to take the XML data reference by the node and view it with a data grid view. Does any one know if this is possible?
I am using the following code:
// submit command to webserver
XmlNode response = SubmitToWebserv((XmlElement)IssueNode, state.Get);
// create XML reader to read response
XmlReader reader = new XmlNodeReader(response);
// create a data table to hold response
DataTable dt = new DataTable();
dt.ReadXmlSchema(reader);
// read data into data table
dt.ReadXml(reader);
It throws exception: DataTable does not support schema inference from Xml. The thing is, the schema is included in the XML referenced by response... So I am at a loss.
I suggest you try that using DataSet instead of DataTable. I don't know that it will work, but it makes sense that it would. The schema might have included more than one table.
OTOH, did the XmlNode include a schema at all?
I recommend you look at this in the debugger. In particular, watch to see which node the XmlReader is positioned on. I'm not 100% convinced it will advance as you want, from the wrapping element, to the schema, then to the data.
Also, is there an element wrapping the schema and data:
<node>
<xs:schema/>
<data/>
</node>
Or are the schema and data elements top-level nodes. This would be a fragment.

Howto parse csv and returns a dataSet as a result

I need a CSVParser class file
A Class File which parses csv and returns a dataSet as a result ASP.Net
I'm pretty sure that CSVReader (CodeProject) can read to DataTable.
DataTable table = new DataTable();
// set up schema... (Columns.Add)
using(TextReader text = File.OpenText(path))
using(CsvReader csv = new CsvReader(text, hasHeaders)) {
table.Load(csv);
}
Note that manually setting up the schema is optional; if you don't, I believe it assumes that everything is string.
Simple google gives plenty of results.
I've had luck with this parser. It will return results to a DataSet.
Another tool you might want to check out is FileHelpers. I see there's a tag for this resource here on SO.

Categories

Resources