I create a form so I use textbox and I would like when I push the button "send" he filled xml :
for exemple 1 time :
<?xml version="1.0" encoding="utf-8"?>
<DonneesLocale>
<Donnee>
<id>1</id>
<libelle>bla </libelle>
<email_asso>bla#</email_asso>
<login>bla</login>
<psw>bla</psw>
<site>bla</site>
<description>bla</description>
<data_1_lib></data_1_lib>
<data_1_val></data_1_val>
<data_2_lib></data_2_lib>
<data_2_val></data_2_val>
</Donnee>
</DonneesLocale>
and 2nd time when I push the button:
<?xml version="1.0" encoding="utf-8"?>
<DonneesLocale>
<Donnee>
<id>1</id>
<libelle>bla </libelle>
<email_asso>bla#</email_asso>
<login>bla</login>
<psw>bla</psw>
<site>bla</site>
<description>bla</description>
<data_1_lib></data_1_lib>
<data_1_val></data_1_val>
<data_2_lib></data_2_lib>
<data_2_val></data_2_val>
</Donnee>
<DonneesLocale>
<Donnee>
<id>2</id>
<libelle>hello</libelle>
<email_asso>hello#</email_asso>
<login>hello</login>
<psw>hello</psw>
<site>hello</site>
<description>hello</description>
<data_1_lib></data_1_lib>
<data_1_val></data_1_val>
<data_2_lib></data_2_lib>
<data_2_val></data_2_val>
</Donnee>
</DonneesLocale>
Someone can help me please ?
(Sorry for my English !)
Thanks !
So if I get it correct, you want to append new data to your existing xml.
For that you can chose to temporarily store the current xml and and add new data to it using Linq Xml.
To do this, now you need to modify your current code with an additional check for xml file exists before all calls to press button event. The code for appending to xml can be found Appending an existing XML file with XmlWriter
If you are using a list of objects then you can update the list on button click and parse your object list in xml like below:
var xml = new XElement("DonneesLocales", DonneesLocalList.Select(x => new XElement("DonneesLocale",
new XElement("Donnee",
new XElement("id"),
new XElement("libelle"),
new XElement("email_asso"),
new XElement("login"),
new XElement("psw"),
new XElement("site"),
new XElement("description"),
new XElement("data_1_lib"),
new XElement("data_1_val"),
new XElement("data_2_lib"),
new XElement("data_2_val")))));
Another option is their for XML Serialization and Deserialization which will be done with the help of XMLSerializer,
public class DonneesLocale
{
private List<Donnee> donnee = new List<Donnee>();
[XmlArray("DonneesLocale")]
public List<Donnee> Donnee
{
get { return donnee; }
set { donnee = value; }
}
}
[XmlType("Donnee")]
public class Donnee
{
[XmlElement("id")]
public int id { get; set; }
[XmlElement("libelle")]
public string libelle { get; set; }
[XmlElement("email_asso")]
public string email_asso { get; set; }
[XmlElement("login")]
public string login { get; set; }
[XmlElement("psw")]
public string psw { get; set; }
[XmlElement("site")]
public string site { get; set; }
[XmlElement("description")]
public string description { get; set; }
[XmlElement("data_1_lib")]
public string data_1_lib { get; set; }
[XmlElement("data_1_val")]
public string data_1_val { get; set; }
[XmlElement("data_2_lib")]
public string data_2_lib { get; set; }
[XmlElement("data_2_val")]
public string data_2_val { get; set; }
}
DonneesLocale dnl = new DonneesLocale();
private void Serialize(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
var temp = new Donnee() { id = i, libelle = "libelle " + i, email_asso = "email_asso " + i, login = "login " + i, psw = "psw " + i, site = "site " + i, description = "description " + i, data_1_lib = "data_1_lib " + i, data_1_val = "data_1_val " + i, data_2_lib = "data_2_lib " + i, data_2_val = "data_2_val " + i };
dnl.Donnee.Add(temp);
}
try
{
// to Save columnorders to the file
var serializer = new XmlSerializer(typeof(DonneesLocale));
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
using (TextWriter writer = new StreamWriter(#"Your XML Path"))
{
serializer.Serialize(writer, dnl, ns);
}
}
catch { }
}
private void Deserialize(object sender, EventArgs e)
{
try
{
if (File.Exists(#"Your XML Path"))
{
var deserializer = new XmlSerializer(typeof(DonneesLocale));
using (TextReader reader = new StreamReader(#"Your XML Path"))
{
dnl = (DonneesLocale)deserializer.Deserialize(reader);
}
}
}
catch
{
}
}
all you need is to add an object to the list and serialize the object to XML whenever you want,
this will work as you expected,
Related
I was finally able to create a Xml file with some coding (with lots of help here from some people). I can store the file but the next process is reading it back. This gave me an error:
"Unexpected Xml declaration". After searching a bit I understand that a Xml file can have only one time <?xml version=1.0 etc>. But my document has several of these statements in the document. And therefore the code
xmlDocument doc = new XmlDocument
Throws me this error. The question is how do I get rid of all these comments in the xml document.
The document is create with 2 functions:
private void btnSave_Click(object sender, EventArgs e)
{
//Check if all fields are filled in
if (txbCompany.Text == "" || txbSiteName.Text == "" || txbIMO.Text == "")
{
MessageBox.Show("Please fill in all empty fields");
}
else if (NumMachTot.Value == 0)
{
MessageBox.Show("A Client profile needs at least one assigned machine!");
}
else
{
var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "VibroManager");
Directory.CreateDirectory(appData);
//Create the Company Profile Class
CompanyProfile companyProfile = new CompanyProfile();
companyProfile.CompanyName = txbCompany.Text;
companyProfile.SiteName = txbSiteName.Text;
companyProfile.Imo = txbIMO.Text;
companyProfile.MachineTotal = (int)NumMachTot.Value;
//Serialization of the companyProfile and append to the document
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(CompanyProfile));
using (var writer = new StreamWriter(Path.Combine(appData, $"{txbCompany.Text}_{txbSiteName.Text}.xml"), true))
{
x.Serialize(writer, companyProfile);
}
//Iterate the datasource list, NOT the DataGridView.
foreach (MachineProfile machineProfile in dsMachineProfile)
{
AppendMachineData(machineProfile, fileName: Path.Combine(appData, $"{txbCompany.Text}_{txbSiteName.Text}.xml"));
}
//Close form and open Main form
this.Hide();
frmMain fMain = new frmMain();
fMain.ShowDialog();
}
}
changed Code:
private void AppendMachineData(MachineProfile machineProfile, string fileName)
{
//Serialization of the MachineProle and append to the document
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(MachineProfile));
var settings = new XmlWriterSettings();
using (var writer = new StreamWriter(fileName, true))
{
settings.Indent = true;
settings.OmitXmlDeclaration = true;
x.Serialize(writer, machineProfile);
}
}
I think in these two functions the problem is created but in fact I do not know why and how. Or maybe there is another way to solve this.
This is the code that I use to read the xml file
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
var filePath = string.Empty;
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData );
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
//Get the path of specified file
filePath = openFileDialog.FileName;
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode node = doc.DocumentElement.SelectSingleNode("/CompanyName");
lblCompanyName.Text = node.InnerText;
}
}
}
Here is a screenshot of the Xml file
Below shows how to use XML serialization which allows one to use classes to store one's data and then serialize these classes to save the data to an XML file. Deserialization reads the data from the XML file and populates the classes.
Try the following:
To each of the classes below, add the following using statements
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
Create a class (name: XmlCompanyProfile.cs)
public class XmlCompanyProfile
{
public string CompanyName { get; set; }
public string SiteName { get; set; }
public int Imo { get; set; }
public int MachineTotal { get; set; }
}
If an element name isn't specified, the name of the property is used in the XML file.
Example 1:
public string CompanyName { get; set; }
By specifying an ElementName, one can make the property name different than the name used in the XML file.
Example 2:
[XmlElement(ElementName = "Name")]
public string CompanyName { get; set; }
Of course, one can also set the value of ElementName to the property name.
Example 3:
[XmlElement(ElementName = "CompanyName")]
public string CompanyName { get; set; }
Note: In Example 3, since the element name is set to the same value as the property name, it will have the same result as Example 1.
If one wishes to specify the element names, the XmlCompanyProfile class will look like the following instead:
public class XmlCompanyProfile
{
[XmlElement(ElementName = "CompanyName")]
public string CompanyName { get; set; }
[XmlElement(ElementName = "SiteName")]
public string SiteName { get; set; }
[XmlElement(ElementName = "Imo")]
public int Imo { get; set; }
[XmlElement(ElementName = "MachineTotal")]
public int MachineTotal { get; set; }
}
Create a class (name: XmlMachineProfile.cs)
public class XmlMachineProfile
{
[XmlElement(ElementName = "MachineName")]
public string MachineName { get; set; }
[XmlElement(ElementName = "NominalSpeed")]
public int NominalSpeed { get; set; }
}
Create a class (name: XmlRoot.cs)
[XmlRoot(ElementName = "Root")]
public class XmlRoot
{
[XmlElement(ElementName = "CompanyProfile")]
public XmlCompanyProfile CompanyProfile { get; set; } = new XmlCompanyProfile();
[XmlElement(ElementName = "MachineProfile")]
public List<XmlMachineProfile> MachineProfiles { get; set; } = new List<XmlMachineProfile>();
}
To serialize and deserialize the data:
Create a class (name: HelperXml.cs)
public static class HelperXml
{
public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
//Usage: Class1 myClass1 = DeserializeXMLFileToObject<Class1>(xmlFilename);
T rObject = default(T);
if (string.IsNullOrEmpty(xmlFilename))
{
throw new Exception($"Error: XML filename not specified (xmlFilename: '{xmlFilename}'");
}
using (System.IO.StreamReader xmlStream = new System.IO.StreamReader(xmlFilename))
{
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
rObject = (T)serializer.Deserialize(xmlStream);
}
return rObject;
}
public static void SerializeObjectToXMLFile(object obj, string xmlFilename)
{
//Usage: Class1 myClass1 = new Class1();
//SerializeObjectToXMLFile(myClass1, xmlFilename);
if (string.IsNullOrEmpty(xmlFilename))
{
throw new Exception($"Error: XML filename not specified (xmlFilename: '{xmlFilename}'");
}
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings() { Indent = true, OmitXmlDeclaration = true};
using (System.Xml.XmlWriter xmlWriter = System.Xml.XmlWriter.Create(xmlFilename, settings))
{
//specify namespaces
System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
ns.Add(string.Empty, "urn:none"); //eliminates "xsd" and "xsi" namespaces
//create new instance
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
//serialize (write to XML file)
serializer.Serialize(xmlWriter, obj, ns);
}
}
}
Usage (serialization):
Note: In the code below, the name of the button is btnSerialize.
private XmlRoot _root = null;
...
private void btnSerialize_Click(object sender, EventArgs e)
{
//create new instance
_root = new XmlRoot();
//set CompanyProfile info
_root.CompanyProfile.CompanyName = "ABB";
_root.CompanyProfile.SiteName = "Rotterdam";
_root.CompanyProfile.Imo = 123456;
_root.CompanyProfile.MachineTotal = 3;
//add machine profile
_root.MachineProfiles.Add(new XmlMachineProfile() { MachineName = "Machine 1", NominalSpeed = 50 });
_root.MachineProfiles.Add(new XmlMachineProfile() { MachineName = "Machine 2", NominalSpeed = 60 });
_root.MachineProfiles.Add(new XmlMachineProfile() { MachineName = "Machine 3", NominalSpeed = 50 });
//prompt user for XML filename
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.FileName = "Test.xml"; //default filename
sfd.Filter = "XML File (*.xml)|*.xml";
sfd.Title = "Save XML file";
if (sfd.ShowDialog() == DialogResult.OK)
{
//serialize
HelperXml.SerializeObjectToXMLFile(_root, sfd.FileName);
}
}
}
Usage (deserialization):
Note: In the code below, the name of the button is btnDeserialize.
private XmlRoot _root = null;
...
private void btnDeserialize_Click(object sender, EventArgs e)
{
//prompt user for XML filename
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Filter = "XML File (*.xml)|*.xml";
ofd.Title = "Open XML file";
if (ofd.ShowDialog() == DialogResult.OK)
{
//deserialize
_root = HelperXml.DeserializeXMLFileToObject<XmlRoot>(ofd.FileName);
System.Diagnostics.Debug.WriteLine($"CompanyName: '{_root.CompanyProfile.CompanyName}'");
}
}
}
Here's what the XML file looks like:
<Root>
<CompanyProfile>
<CompanyName>ABB</CompanyName>
<SiteName>Rotterdam</SiteName>
<Imo>123456</Imo>
<MachineTotal>3</MachineTotal>
</CompanyProfile>
<MachineProfile>
<MachineName>Machine 1</MachineName>
<NominalSpeed>50</NominalSpeed>
</MachineProfile>
<MachineProfile>
<MachineName>Machine 2</MachineName>
<NominalSpeed>60</NominalSpeed>
</MachineProfile>
<MachineProfile>
<MachineName>Machine 3</MachineName>
<NominalSpeed>50</NominalSpeed>
</MachineProfile>
</Root>
Resources:
XML serialization
Examples of XML Serialization
XDocument Class
JSON Utils
I have a list of Invoice and I have to deserializate it. First I serialized to xml and it ways easy to find and apply. This time I can not deserializate the Item lists in the xml. For example, this is my xml serialized row:
<?xml version="1.0" encoding="utf-8"?>
<Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Invoice>4711</Invoice>
<Table>8</Table>
<Outlet>3</Outlet>
<User>17</User>
<Creation>20140101</Creation>
<Item>
<Type>Revenue</Type>
<Productgroup>5</Productgroup>
<TotalAmount>6</TotalAmount>
<TaxClassification>1</TaxClassification>
<Text>Pizza Tonna</Text>
</Item>
<Item>
<Type>Gratuity</Type>
<TotalAmount>1.5</TotalAmount>
<Text>Tip</Text>
</Item>
<Item>
<Type>Payment</Type>
<TotalAmount>7.5</TotalAmount>
<ResNo>4812</ResNo>
</Item>
</Body>
As you see, I have a Body root xml and 5 mainly row but in the deep I have more than one Item data which is a list. If I had one item for each Invoice, it would be easy to do but during tough researches, I could not get any point.
Let me sahre with you what I did. These are my Body and Item Classes:
[XmlRoot("Body")]
public class Body
{
[XmlElement("Invoice")]
public int Invoice { get; set; }
[XmlElement("Table")]
public int Table { get; set; }
[XmlElement("Outlet")]
public int Outlet { get; set; }
[XmlElement("User")]
public int User { get; set; }
[XmlElement("Creation")]
public int Creation { get; set; }
[XmlElement("Item")]
public List<Item> Items { get; set; }
}
[XmlRoot("Item")]
public class Item
{
[XmlElement("Type")]
public string? Type { get; set; }
[XmlElement("Productgroup")]
public int? Productgroup { get; set; }
public bool ShouldSerializeProductgroup()
{
return Productgroup.HasValue;
}
[XmlElement("TotalAmount")]
public double? TotalAmount { get; set; }
public bool ShouldSerializeTotalAmount()
{
return TotalAmount.HasValue;
}
[XmlElement("TaxClassification")]
public double? TaxClassification { get; set; }
public bool ShouldSerializeTaxClassification()
{
return TaxClassification.HasValue;
}
[XmlElement("Text")]
public string? Text { get; set; }
[XmlElement("ResNo")]
public int? ResNo { get; set; }
public bool ShouldSerializeResNo()
{
return ResNo.HasValue;
}
}
And here is my main program for serialization and nice versa.
static void Main(string[] args)
{
try
{
Body body = new Body
{
Invoice = 4711,
Table = 8 / 1,
Outlet = 3,
User = 17,
Creation = 20140101,
Items = new List<Item>()
{
new Item{Type="Revenue",Productgroup = 5,TotalAmount=6.00,TaxClassification=1,Text="Pizza Tonna"},
new Item{Type="Gratuity",TotalAmount=1.50,Text="Tip"},
new Item{Type="Payment",TotalAmount=7.50,ResNo=4812}
}
};
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Body));
StreamWriter sw = new StreamWriter("CloseInvoice.xml");
xmlSerializer.Serialize(sw, body);
sw.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
try
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Body));
StreamReader sr = new StreamReader("CloseInvoice.xml");
Body body = (Body)xmlSerializer.Deserialize(sr);
Console.WriteLine("Invoice Information");
Console.WriteLine("Type: "+body.Invoice);
Console.WriteLine("Table: " + body.Table);
Console.WriteLine("Outlet: " + body.Outlet);
Console.WriteLine("User: " + body.User);
Console.WriteLine("Creation: " + body.Creation);
}
catch (Exception)
{
throw;
}
}
I tried all loops but I cannot write the Items on the console. Can you please help me? Thank from now.
Edit: Here is my console out. I can get Body Rows but I want to get Item List in the xml too.
What is your problem ? It's working for me:
for (int i = 0; i < body.Items.Count; i++)
{
var item = body.Items[i];
Console.WriteLine("ProductGroup: " + item.Productgroup);
Console.WriteLine("ResNo: " + item.ResNo);
Console.WriteLine("TaxClassification: " + item.TaxClassification);
Console.WriteLine("Text: " + item.Text);
Console.WriteLine("TotalAmount: " + item.TotalAmount);
Console.WriteLine("Type: " + item.Type);
}
Well, It seems you're interested in just looping through the Body.Items collection here. So, I think #Pierre Michel's covers that.
However, given your comments, I want to extend on that answer by including the use of Reflection with PropertyInfo of the type Item.
My answer will showcase conditionally checking for the existence of a value being specified. (i.e. when not null as a reference type, and not the default value when a value type.
For each PropertyInfo in each instance of Item, we'll do a conditional check on whether that Property is null or default, and we'll perform a Console.Write when a value is determined to exist and be specified (and not default).
Note we'll include using System.Reflection; in the file.
foreach (var item in body.Items)
{
WriteItemPropertiesThatHaveValues(item);
}
void WriteItemPropertiesThatHaveValues<T>(T item)
{
foreach (PropertyInfo pi in typeof(Item).GetProperties())
{
WriteItemPropertyThatHasValue(item, pi);
}
Console.WriteLine();
}
void WriteItemPropertyThatHasValue<T>(T item, PropertyInfo pi)
{
T defaultTValue = default;
var itemValue = pi.GetValue(item);
if (!(itemValue?.Equals(defaultTValue) ?? true))
Console.WriteLine($"\t{pi.Name} => { itemValue }");
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<Images>
<I0>
<Path>123.com</Path>
<I0>
<I1>
<Path>123.com</Path>
<I1>
<I2>
<Path>123.com</Path>
<I2>
</Images>
Can serializer.Deserialize() be used to get tags with different names into a collection?
currently, in my object I have:
C#:
public class rootObject
{
[XmlElement(ElementName = "I0")]
public I0 I0 { get; set; }
[XmlElement(ElementName = "I1")]
public I1 I1 { get; set; }
[XmlElement(ElementName = "I2")]
public I2 I2 { get; set; }
}
But I would like to have (Because Images can have more or fewer elements):
public class rootObject
{
public List<I> Is { get; set; }
}
You can do what you are suggesting you just merely need to pass in the type argument in your class doing the generic. The key point to remember when you do a deserialization routine is that the routine needs to know the sub reference. So if I was to say string.Deserialize it would bomb. It would need to know a reference string.Deserialize> where Sub could be the class object that may change.
Say I have a base class and I want 'T' to be a type I can change for extensible abilities later.
[Serializable]
public class Test<T> where T : class
{
public Test() { }
public int TestId { get; set; }
public string Name { get; set; }
public List<T> Shipments { get; set; }
}
I want to test this with two classes I just make up that have different properties slightly
[Serializable]
public class Sub1
{
public int Id { get; set; }
public string Desc { get; set; }
}
[Serializable]
public class Sub2
{
public int IdWhatever { get; set; }
public string DescWhatever { get; set; }
}
Now let's do a main program and test serialization.
class Program
{
static void Main(string[] args)
{
var serializeTest = new Test<Sub1> { TestId = 1, Name = "Test", Shipments = new List<Sub1> { new Sub1 { Id = 1, Desc = "Test" }, new Sub1 { Id = 2, Desc = "Test2" } } };
var serializeTest2 = new Test<Sub2> { TestId = 1, Name = "Test", Shipments = new List<Sub2> { new Sub2 { IdWhatever = 1, DescWhatever = "Test" }, new Sub2 { IdWhatever = 2, DescWhatever = "Test2" } } };
var serialized = serializeTest.SerializeToXml();
var serialized2 = serializeTest2.SerializeToXml();
var deserialized = serialized.DeserializeXml<Test<Sub1>>();
var deserialized2 = serialized2.DeserializeXml<Test<Sub2>>();
Console.WriteLine(serialized);
Console.WriteLine();
Console.WriteLine(serialized2);
Console.ReadLine();
}
}
And my Serialize and DeSerialize extension methods:
public static string SerializeToXml<T>(this T valueToSerialize, string namespaceUsed = null)
{
var ns = new XmlSerializerNamespaces(new XmlQualifiedName[] { new XmlQualifiedName(string.Empty, (namespaceUsed != null) ? namespaceUsed : string.Empty) });
using (var sw = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
dynamic xmler = new XmlSerializer(typeof(T));
xmler.Serialize(writer, valueToSerialize, ns);
}
return sw.ToString();
}
}
public static T DeserializeXml<T>(this string xmlToDeserialize)
{
dynamic serializer = new XmlSerializer(typeof(T));
using (TextReader reader = new StringReader(xmlToDeserialize))
{
return (T)serializer.Deserialize(reader);
}
}
You don't need to specify the XmlElement name when the properties match the XML. A few solutions, some kinda hacky :).
HACKY: use regex string replace to replace <I#> and </I#> to
just <I> and </I>
SOMEWHAT HACKY: This might work for you:
How to deserialize an XML array containing multiple types of elements in C#,
but you'd have to add an attribute for i0, i1 ... i100, etc.
BEST: Is that your entire XML? I'd honestly just use LINQToXml and
do a Descendants("Path") and get an array of strings back with 1 line of code. Serialization is not really the best solution for this.
I am trying to convert a html list to xml format with a console application, but i did what i planned and now i dont know how to continue. I will share my code and explain a bit. What i dont know for now , and is confusing me is where the 'magic' happens. Ok i know i have to take that list from the page , read the list with all the tags inside, but what next, how can i transform that list into xml format? I am new to xml i know some basics so please help me.
Here is the application :
static void Main(string[] args)
{
string _url = "http://example.com/media";
int newsCounter = 0;
List<News> _newsList = new List<News>();
HtmlWeb web = new HtmlWeb();
HtmlDocument doc = web.Load(_url);
HtmlNode ulNode = doc.DocumentNode.SelectSingleNode("//ul[#class='content articles']");
HtmlNodeCollection liNode = ulNode.SelectNodes(".//li");
foreach (HtmlNode node in ulNode.SelectNodes(".//div[#class='article_box']"))
{
var news = new News();
news.Imgsrc = node.FirstChild.SelectSingleNode("//img").Attributes["src"].Value;
var nodes = doc.DocumentNode.FirstChild.SelectNodes("//img[#src]");
foreach (HtmlNode childNode in node.SelectNodes(".//div[#class='box_info']"))
{
// string src = node.SelectSingleNode("//img").Attributes["src"].Value;
foreach(HtmlNode _node in childNode.SelectNodes(".//h3"))
{
news.Link = "";
news.Title = _node.FirstChild.InnerText;
news.Date = _node.NextSibling.NextSibling.InnerText;
news.Text = _node.NextSibling.NextSibling.NextSibling.NextSibling.InnerText;
}
}
_newsList.Add(news);
newsCounter++;
}
and also the News class :
public class News
{
public string Imgsrc { get; set; }
public string Title { get; set; }
public string Link { get; set; }
public string Date { get; set; }
public string Text { get; set; }
}
these are all the parameters i have to read from the list.I am able to read them and return all of the news in my list , but what next , how to transform my list into xml format? Any suggestions are welcomed.
There are many way of creating xml. There are not a lot of items in your case so just using Xml linq is very simple. Putting it into a class may produce cleaner code or you can just use the code directly like Sledge suggested.
public class News
{
public string Imgsrc { get; set; }
public string Title { get; set; }
public string Link { get; set; }
public string Date { get; set; }
public string Text { get; set; }
public XElement ToXml()
{
return new XElement("news", new object[] {
new XElement("Imgscr", Imgsrc),
new XElement("Title", Title),
new XElement("Link", Link),
new XElement("Date", Date),
new XElement("Text", Text),
});
}
}
Thanks to everyone guys. I marked 'News' class as Serializable and with a few lines of code managed to generate the xml file. Here is the code, really simple :
XmlSerializer serializer = new XmlSerializer(typeof(List<News>));
using (TextWriter writer = new StreamWriter(#"D:\News.xml"))
{
serializer.Serialize(writer, _newsList);
}
I have spent hours trying to figure out why my database cannot find the table I have found numerous examples and none have seemed to help. I have created a separate class to handle the database operations so I can use it on multiple pages.
Here is the code
[Table]
public class MatchItem
{
[Column(IsPrimaryKey = true, CanBeNull=false,IsDbGenerated=true)]
public int MatchID { get; set; }
[Column(CanBeNull = false)]
public string MatchNumber { get; set; }
[Column(CanBeNull = false)]
public string EventName { get; set; }
[Column(CanBeNull = false)]
public DateTime Time { get; set; }
[Column(CanBeNull = false)]
public string[] RedTeams { get; set; }
[Column(CanBeNull = false)]
public string[] BlueTeams { get; set; }
[Column(CanBeNull = false)]
public int RedFinal { get; set; }
[Column(CanBeNull = false)]
public int BlueFinal{ get; set; }
}
Here is the Data context
public class MatchDataContext:DataContext
{
public MatchDataContext(string connectionString) :
base(connectionString)
{
}
public Table<MatchItem> Matches
{
get
{
return this.GetTable<MatchItem>();
}
}
}
I made a class so I could use it on multiple pages
public class MatchDBManager
{
private static string connectionString = #"Data Source=isostore:/DB.sdf";
public MatchDBManager()
{
initialize();
}
public void initialize()
{
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
if (Mchdb.DatabaseExists())
{
Console.WriteLine("DB already exists");
}
else
{
Mchdb.CreateDatabase();
Console.WriteLine("DB created");
}
}
}
public void addMatchData(IList<MatchItem> data)
{
//this.clearData();
//initialize();
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
Mchdb.Matches.InsertAllOnSubmit(data);
Mchdb.SubmitChanges();
}
}
public IList<MatchItem> getTeamData(string teamNum)
{
IList<MatchItem> MatchList = null;
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
IQueryable<MatchItem> mchQuery = from mch in Mchdb.Matches where (mch.RedTeams[0] == teamNum || mch.RedTeams[1] == teamNum || mch.RedTeams[2] == teamNum || mch.BlueTeams[0] == teamNum || mch.BlueTeams[1] == teamNum || mch.BlueTeams[2] == teamNum) select mch;
MatchList = mchQuery.ToList();
}
return MatchList;
}
public IList<MatchItem> getEventData(string eventID)
{
IList<MatchItem> MatchList = null;
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
IQueryable<MatchItem> mchQuery = from mch in Mchdb.Matches where mch.Event == eventID select mch;
MatchList = mchQuery.ToList();
}
return MatchList;
}
private void clearData()
{
using (MatchDataContext Mchdb = new MatchDataContext(connectionString))
{
if (Mchdb.DatabaseExists())
{
Mchdb.DeleteDatabase();
}
}
}
}
I have the error The specified table does not exist[Match].
Added here is where I download
public IList<MatchItem> ParseXML(XmlReader reader)
{
//List<string> save = new List<string>();
List<MatchItem> MatchList= new List<MatchItem>();
XElement matchData;
matchData = XElement.Load(reader);
StringBuilder output = new StringBuilder();
int count = 0;
var matches = from item
in matchData.Elements("match")
select item;
foreach (XElement eachmatch in matches)
{
MatchItem mch = new MatchItem();
string Time = ((eachmatch.Element("pubdate").Value).ToString());
mch.EventName = ((eachmatch.Element("event").Value).ToString());
mch.MatchNumber = ((eachmatch.Element("mch").Value).ToString() + (eachmatch.Element("typ").Value).ToString());
string[] RT = { eachmatch.Element("red1").Value.ToString(), eachmatch.Element("red2").Value.ToString(), eachmatch.Element("red3").Value.ToString() };
string[] BT = { eachmatch.Element("blue1").Value.ToString(), eachmatch.Element("blue2").Value.ToString(), eachmatch.Element("blue3").Value.ToString() };
string RF = ((eachmatch.Element("rfin").Value).ToString());
string BF = ((eachmatch.Element("bfin").Value).ToString());
// Time = Time.Substring(0, (Time.IndexOf("+") - 1));
mch.Time = DateTime.Parse(Time);
mch.RedTeams = RT;
mch.BlueTeams = BT;
mch.RedFinal = int.Parse(RF);
mch.BlueFinal= int.Parse(BF);
mch.MatchID = count;
count += 1;
MatchList.Add(mch);
}
return MatchList;
}
This is where I call this method
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
initializeDB();
if (e.Error == null)
{
XmlReader reader = XmlReader.Create(new StringReader(e.Result));
DownloadInfo di = new DownloadInfo();
IList <MatchItem>data= di.ParseXML(reader);
outputer(data);
addData(data.ToList<MatchItem>());
}
else
{
IList<MatchItem> data = getTeamData(strMyTeam);
outputer(data);
}
}
I ended up removing the DatabaseManager class and putting the functions in the main code
Then I output them to the screen here
public void outputer(IList<MatchItem> mch)
{
for (int i = 0; i < mch.Count; i++)
{
Score sc = new Score();
sc.Width = lsbData.Width;
sc.Height = sc.Height;
sc.Time = mch[i].Time.ToString();
sc.Event = mch[i].EventName;
sc.RT = mch[i].RedTeams[0] + " " + mch[i].RedTeams[1] + " " + mch[i].RedTeams[2];
sc.BT = mch[i].BlueTeams[0] + " " + mch[i].BlueTeams[1] + " " + mch[i].BlueTeams[2];
sc.RF = mch[i].RedFinal.ToString();
sc.BF = mch[i].BlueFinal.ToString();
lsbData.Items.Add(sc);
}
}
*note:score is a custom control that works(and worked) before the database code *
I don't see where you actually create a Match Object.
if you have you need to include that code in the question as well. and if you haven't, that would explain why it doesn't exist.
Addition
in order to add Match Objects to a list you will have to create the objects first then add them to the list, I don't think you can create the whole list of objects before creating each individual object.
more Additional Information
the object still needs to be created before you can add items to it. that is what the error is telling you. you don't have the object to insert data into.
Match Table1 = new Match();
this creates a new Match object which allows you to access the pieces of the object and insert data into the object like this
Table1.MatchNumber = 42
you can't add to something to a memory location until you set aside that memory location for that specific person and give it a name.
when you create that class you can add functions and all sorts of fun stuff to it, but you can't use any of it until you have created a Match Object.
you can't add something to a list that doesn't exist, you have to create the Match Object first, then add it to the list