I have an XML file, and when I used XSD tool to create a class object from the XML, I get a message saying "A column named 'link' already belongs to this DataTable: cannot set a nested table to the same name.
I want to know how I can correctly deserialize this XML file so that I can display the data on an app. This XML file is basically just Rss news feed data.
You can see the entire XML file structure here: https://github.com/karimo94/XMLDemo/blob/master/leaguenews.xml
Look at this design
https://blogs.windows.com/buildingapps/2017/05/01/master-master-detail-pattern/#.WSrAkFuGID4.twitter#7gkbxLDhEVrcmL6M.97
DataSet ds = new DataSet();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(DataSet));
FileStream readStream = new FileStream("leaguenews.xml", FileMode.Open);
ds = (DataSet)xmlSerializer.Deserialize(readStream);
readStream.Close();
dataGridView1.DataSource = ds.Tables[0];
Try followng :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Description", typeof(string));
dt.Columns.Add("Link", typeof(string));
dt.Columns.Add("IsPermaLink", typeof(Boolean));
dt.Columns.Add("GUID", typeof(string));
dt.Columns.Add("Publish Date", typeof(DateTime));
dt.Columns.Add("Width", typeof(int));
dt.Columns.Add("Height", typeof(int));
dt.Columns.Add("URL", typeof(string));
XDocument doc = XDocument.Load(FILENAME); //or uri
List<XElement> items = doc.Descendants("item").ToList();
foreach (XElement item in items)
{
dt.Rows.Add(new object[] {
(string)item.Element("title"),
(string)item.Element("description"),
(string)item.Element("link"),
(Boolean)item.Element("guid").Attribute("isPermaLink"),
(string)item.Element("guid"),
(DateTime)item.Element("pubDate"),
(int)item.Elements().Where(x => x.Name.LocalName == "thumbnail").FirstOrDefault().Attribute("width"),
(int)item.Elements().Where(x => x.Name.LocalName == "thumbnail").FirstOrDefault().Attribute("height"),
(string)item.Elements().Where(x => x.Name.LocalName == "thumbnail").FirstOrDefault().Attribute("url")
});
}
}
}
}
I tried both ways and honestly, I couldn't get it to deserialize properly without errors. Luckily, I was able to use rss2json.com and that converted the Rss feed into a json which I could parse using Newtonsoft Json.Net
Related
i am getting the following response from api as xml
<ROOT>
<valid>1</valid>
<org_name> test org </org_name>
<count_of_vedios>3</count_of_vedios>
<total_length>351</total_length>
<Video1>
<Title>The Distinguished Gentleman</Title>
<Director>Jonathan Lynn</Director>
<Length>112 Minutes</Length>
<Format>DVD</Format>
<Rating>R</Rating>
</Video1>
<Video2>
<Title>Her Alibi</Title>
<Director>Bruce Beresford</Director>
<Length>94 Mins</Length>
<Format>DVD</Format>
<Rating>PG-13</Rating>
</Video2>
<Video3>
<Title>Chalte Chalte</Title>
<Director>Aziz Mirza</Director>
<Length>145 Mins</Length>
<Format>DVD</Format>
<Rating>N/R</Rating>
</Video3>
</ROOT>
i need to fill some fields of aspx page with the information :
org_name : test org
count_of_vedios : 3
total_length : 351
also i need to fill gridview with the vedios that is in nodes
Title | Director | Length | Format | Rating |
dataset will have 4 tables here , so what i did is replace the vedio# tage with vedio , now the dataset will have 2 tables one for the general nodes and the another for vedios
DataTable general_dt = new DataTable();
DataTable vedios_dt = new DataTable();
string xml_str = document.DocumentElement.InnerXml.ToString();
xml_str = Regex.Replace(xml_str, #"<Video[0-9]{1,3}>", "<Video>");
xml_str = Regex.Replace(xml_str, #"<\/Video[0-9]{1,3}>", "</Video>");
DataSet ds = new DataSet();
ds.ReadXml(new System.IO.StringReader(xml_str));
if (ds.Tables.Count > 0)
{
XmlNode newnode;
newnode = document.ReadNode(new XmlTextReader(new StringReader(xml_str)));
if (newnode["valid"].InnerText.ToString() == "1")
{
general_dt = ds.Tables[0];
vedios_dt = ds.Tables[1];
}
}````
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Title", typeof(string));
dt.Columns.Add("Directory", typeof(string));
dt.Columns.Add("Length", typeof(string));
dt.Columns.Add("Format", typeof(string));
dt.Columns.Add("Rating", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
List<XElement> videos = doc.Root.Elements().Where(x => x.Name.LocalName.StartsWith("Video")).ToList();
foreach (XElement video in videos)
{
dt.Rows.Add(new object[] {
(string)video.Element("Title"),
(string)video.Element("Director"),
(string)video.Element("Length"),
(string)video.Element("Format"),
(string)video.Element("Rating")
});
}
}
}
}
I try to display every "package" element in datagridview. But it looks like it only show version 1.02. here is my code :
private void button1_Click(object sender, EventArgs e)
{
string path = Environment.CurrentDirectory;
DataTable dt = new DataTable();
dt.Columns.Add("version", typeof(string));
dt.Columns.Add("sha1sum", typeof(string));
dt.Columns.Add("url", typeof(string));
dt.Columns.Add("ps3_system_ver", typeof(string));
dt.Columns.Add("size", typeof(string));
XmlDocument xDoc = new XmlDocument();
xDoc.Load(path + #"\\temp\\BCES01893-ver.xml");
XDocument doc = XDocument.Load(path + #"\\temp\\BCES01893-ver.xml");
XmlNodeList p = xDoc.GetElementsByTagName("package");
for (int i = 0; i < p.Count; i++)
{
if (p.Count > 0)
{
foreach (XElement addresdm in doc.Descendants().Where(x => x.Name.LocalName == "tag"))
{
XElement avee = addresdm.Descendants("package").FirstOrDefault();
dt.Rows.Add(new object[] {
(string)avee.Attribute("version"),
(string)avee.Attribute("sha1sum"),
(string)avee.Attribute("url"),
(string)avee.Attribute("ps3_system_ver"),
(string)avee.Attribute("size"),
});
}
}
dataGridView1.DataSource = dt;
}
}
xml file :
<titlepatch status="alive" titleid="BCES01893">
<tag name="BCES01893_T359" popup="true" signoff="true" min_system_ver="03.60">
<package version="01.02" size="1315387312" sha1sum="d68d0584aa30b6d02a7aee95236f91ef43fdc11e" url="http://b0.ww.np.dl.playstation.net/tppkg/np/BCES01893/BCES01893_T359/b80952de9329a9ba/EP9001-BCES01893_00-0000000000000000-A0102-V0101-PE.pkg" ps3_system_ver="04.4000"/>
<package version="01.03" size="102857792" sha1sum="7b1c6b9dd621ed9a5ae130737bfa5a4dd386db66" url="http://b0.ww.np.dl.playstation.net/tppkg/np/BCES01893/BCES01893_T359/b80952de9329a9ba/EP9001-BCES01893_00-0000000000000000-A0103-V0100-PE.pkg" ps3_system_ver="04.4000"/>
<package version="01.04" size="223699280" sha1sum="4cedbc07c384b0f5556d5f0697b03c81376fd89d" url="http://b0.ww.np.dl.playstation.net/tppkg/np/BCES01893/BCES01893_T359/b80952de9329a9ba/EP9001-BCES01893_00-0000000000000000-A0104-V0100-PE.pkg" ps3_system_ver="04.4000"/>
</package>
</tag>
</titlepatch>
the result : https://i.ibb.co/cQJRFzj/Untitled.png
how can i make it display correctly?
You are only getting last item because following is inside for loop : dataGridView1.DataSource = dt;Move outside for loop.
Here is my code which is a little simpler.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Data;
namespace ConsoleApplication103
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("version", typeof(string));
dt.Columns.Add("sha1sum", typeof(string));
dt.Columns.Add("url", typeof(string));
dt.Columns.Add("ps3_system_ver", typeof(string));
dt.Columns.Add("size", typeof(string));
XDocument doc = XDocument.Load(FILENAME);
foreach (XElement addresdm in doc.Descendants("package"))
{
dt.Rows.Add(new object[] {
(string)addresdm.Attribute("version"),
(string)addresdm.Attribute("sha1sum"),
(string)addresdm.Attribute("url"),
(string)addresdm.Attribute("ps3_system_ver"),
(string)addresdm.Attribute("size"),
});
}
}
}
}
Create xml file with dataset like this format-
-<_XPXML Note="" CrtTime="" CN="" DBN="" Srv="" Ver="" AppId="" Class="" IC="" Stock="" Desc="">
<_InvTrans IC="010006" Stock="1" Desc="2 " OppKind="1" Amount="744" Batch="6" Mat="108208"/>
<_InvTrans IC="010006" Stock="1" Desc="2 " OppKind="1" Amount="744" Batch="6" Mat="108208"/>
<_InvTrans IC="010006" Stock="1" Desc="2 " OppKind="1" Amount="744" Batch="6" Mat="108208"/>
</_XPXML>
If you want to create some custom xml that you can use XElement.
How to create <_XPXML Note="" CrtTime="" CN="" DBN="" Srv="" Ver="" AppId="" Class="" IC="" Stock="" Desc="">?
You can use the code below to create.
var node=new XElement("_XPXML ");
node.SetAttributeValue("Note","");
node.SetAttributeValue("CrtTime","");
// ...
// please write the Attribute
doc.Root.Add(node);
Before you use the code that you should new doc as this code
XDocument doc = new XDocument();
And you should add using System.Xml.Linq in file top.
After you set the attribute that you can save it to file.
doc.Save(xx);
The example:
XDocument doc = new XDocument();
XElement node = new XElement("_XPXML");
node.SetAttributeValue("Note", "");
var invTrans = new XElement("_InvTrans");
node.Add(invTrans);
invTrans.SetAttributeValue("IC", "010006");
doc.Add(node);
StringBuilder str = new StringBuilder();
TextWriter stream = new StringWriter(str);
doc.Save(stream);
The str is
<?xml version="1.0" encoding="utf-16"?>
<_XPXML Note="">
<_InvTrans IC="010006" />
</_XPXML>
Try following using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication23
{
class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable("_InvTrans");
dt.Columns.Add("IC", typeof(string));
dt.Columns.Add("Stock", typeof(string));
dt.Columns.Add("Desc", typeof(string));
dt.Columns.Add("OppKind", typeof(string));
dt.Columns.Add("Amount", typeof(string));
dt.Columns.Add("Batch", typeof(string));
dt.Columns.Add("Mat", typeof(string));
dt.Rows.Add(new object[] { "010006", "1", "2 ", "1", "744", "6", "108208" });
dt.Rows.Add(new object[] { "010006", "1", "2 ", "1", "744", "6", "108208" });
dt.Rows.Add(new object[] { "010006", "1", "2 ", "1", "744", "6", "108208" });
GetXmlTable(dt);
}
static XElement GetXmlTable(DataTable dt)
{
string tableName = dt.TableName;
XElement table = new XElement(tableName);
string[] columnNames = dt.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray();
foreach (DataRow row in dt.AsEnumerable())
{
XElement xRow = new XElement("_InvTrans");
table.Add(xRow);
foreach (string columnName in columnNames)
{
xRow.Add(new XAttribute(columnName, row[columnName]));
}
}
return table;
}
}
}
I'm iterating parallel in 2 Xml docs. When an element value X from first Xml is
equal to the value in the second Xml (ex. USD== USD), it should write a
row in a DataTable with two columns. Element value X (USD) in the first Column
and an other child element value Y (value from ) from first Xml in the second col.
The second Xml has a single node with multiple elements.
DataTable dTable = new DataTable();
dTable.Columns.Add("ColumnOne");
dTable.Columns.Add("ColumnTwo");
DataRow dRow = null;
foreach (XmlNode nodeFirst in firstXmlDoc.SelectNodes("//ValCurs/Valute"))
{
foreach (XmlNode nodeSecond in secondXmlDoc.SelectSingleNode("SelectedVal"))
{
if (nodeFirst.SelectSingleNode("CharCode").InnerText == nodeSecond.InnerText)
{
dRow = dTable.NewRow();
dRow["ColumnOne"] = nodeFirst.SelectSingleNode("CharCode").InnerText;
dRow["ColumnTwo"] = nodeFirst.SelectSingleNode("Value").InnerText;
dTable.Rows.Add(dRow);
}
}
}
myDataGridView.DataSource = dTable;
This isn't working, I get in "nodeFirst.SelectSingleNode("Value").InnerText" a null value (" ") and it stops, filling the DataTable just with the "CharCode" value.
It's interesting that it worked the first few times I runned it, but it doesn't anymore.
First Xml:
<ValCurs>
<Valute ID="47">
<NumCode>978</NumCode>
<CharCode>EUR</CharCode>
<Nominal>1</Nominal>
<Name>Euro</Name>
<Value>20.3457</Value>
</Valute>
<Valute ID="44">
<NumCode>840</NumCode>
<CharCode>USD</CharCode>
<Nominal>1</Nominal>
<Name>Dolar S.U.A.</Name>
<Value>17.4603</Value>
</Valute>
...
</ValCurs>
Second Xml:
<SelectedVal>
<Cod>UAH</Cod>
<Cod>EUR</Cod>
<Cod>CAD</Cod>
<Cod>RON</Cod>
<Cod>NOK</Cod>
<Cod>RUB</Cod>
<Cod>JPY</Cod>
<Cod>AUD</Cod>
</SelectedVal>
Try following code using xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string CURRENCY_FILE = #"c:\temp\test.xml";
const string COUNTRY_FILE = #"c:\temp\test1.xml";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NUMCODE", typeof(int));
dt.Columns.Add("CHARCODE", typeof(string));
dt.Columns.Add("Nominal", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Value", typeof(decimal));
XDocument currencyXml = XDocument.Load(CURRENCY_FILE);
List<XElement> valutes = currencyXml.Descendants("Valute").ToList();
foreach (XElement valute in valutes)
{
dt.Rows.Add(new object[] {
(int)valute.Attribute("ID"),
(int)valute.Element("NumCode"),
(string)valute.Element("CharCode"),
(int)valute.Element("Nominal"),
(string)valute.Element("Name"),
(decimal)valute.Element("Value")
});
}
XDocument countryXml = XDocument.Load(COUNTRY_FILE);
List<string> countries = countryXml.Descendants("Cod").Select(x => (string)x).ToList();
DataTable filteredTable = dt.AsEnumerable().Where(x => countries.Contains(x.Field<string>("CharCode"))).CopyToDataTable();
}
}
}
i am trying to write c# code to extract columns of data. my data looks like
what should be the regular expression if i want to extract "everything" "under" a column header for example "COMMAND" or "PID".
No need to use regular expression. String Split method will work. Try code like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
namespace ConsoleApplication53
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("PID", typeof(int));
dt.Columns.Add("TT", typeof(string));
dt.Columns.Add("STAT", typeof(string));
dt.Columns.Add("TIME", typeof(DateTime));
dt.Columns.Add("COMMAND", typeof(string));
StreamReader reader = new StreamReader(FILENAME);
int lineCount = 0;
string inputLine = "";
while ((inputLine = reader.ReadLine) != null)
{
if (++lineCount > 2)
{
string[] inputArray = inputLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
dt.Rows.Add(new object[] {
int.Parse(inputArray[0]),
inputArray[1],
inputArray[2],
DateTime.Parse(inputArray[3]),
inputArray[4]
});
}
}
}
}
}