So I need to create a method that makes an XML file from a database, I have already written the stored procedures that get the information from a database for the XML now I only need to write the part where I convert my database to a XML file using the properties of another class that I have written as nodes.
public string CreateXML(Object YourClassObject){
XmlDocument xmlDoc =new XmlDocument(); //Represents an XML document,
// Initializes a new instance of the XmlDocument class.
XmlSerializer xmlSerializer = new XmlSerializer(YourClassObject.GetType());
// Creates a stream whose backing store is memory.
using (MemoryStream xmlStream =new MemoryStream())
{
xmlSerializer.Serialize(xmlStream, YourClassObject);
xmlStream.Position = 0;
//Loads the XML document from the specified string.
xmlDoc.Load(xmlStream);
return xmlDoc.InnerXml;
}
}
This is some code I found online I think I can use for serializing my model, but i'm accessing the database over an event that I created (I'll provide the code tomorrow when I get to work). Anyway I'm accesing the database in the event like the following e.DataTable. Any ideas anybody?
My model looks like the following:
public class DataModel
{
string Sifra {get; set;}
public string Naziv {get; set;}
public string JM {get; set;}
public int Kolicina {get; set;}
public float Cena_x0020_vp {get; set;}
public float Cena_x0020_mp {get; set;}
public float Cena_x0020_bod {get; set;}
public string Slika {get; set;}
public string Grupa {get; set;}
}
This is a sample of how my generated XML should look like.
<?xml version="1.0" encoding="UTF-8"?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2019-04-17T19:13:54">
<row>
<Sifra>ADA110-100</Sifra>
<Naziv_x0020_artikla>Adapter 220/110VAC 100W</Naziv_x0020_artikla>
<JM>kom</JM>
<Kolicina>1</Kolicina>
<Cena_x0020_vp>2683.33</Cena_x0020_vp>
<Cena_x0020_mp>3220</Cena_x0020_mp>
<Cena_x0020_bod>28</Cena_x0020_bod>
<Slika1> ada110v.jpg</Slika1>
<Grupa>Adateri 110V AC</Grupa>
</row>
Problem solved:
private void CreateXML(DataTable dataTable)
{
var list = new List<Row>();
XmlSerializer writer = new XmlSerializer(typeof(List<Row>));
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\ExportZaWeb.xml";
FileStream file = File.Create(path);
foreach (DataRow row in dataTable.Rows)
{
Row r = new Row();
r.Naziv = row["Naziv Artikla"].ToString();
r.JM = row["JM"].ToString();
r.Kolicina = row["Kolicina"].ToString();
r.Cena_x0020_vp = row["Cena vp"].ToString();
r.Cena_x0020_mp = row["Cena mp"].ToString();
r.Cena_x0020_bod = row["Cena bod"].ToString();
r.Slika = row["Slika1"].ToString();
r.Grupa = row["Grupa"].ToString();
list.Add(r);
}
writer.Serialize(file, list);
file.Close();
}
Why not let the stored procedure return the xml for you. The query in the stored procedure would lool something like this:
SELECT Sifra, Naziv, JM, Kolicina, Cena_x0020_vp, Cena_x0020_mp, Cena_x0020_bod, Slika, Grupa
FROM DataModel
FOR XML AUTO
Create a method which takes in a list or IEnumerable object of the Models and returns a string containing the XML (untested, but should get you started), this is assuming you already have the database data in usable objects:
public string GetXmlForModels(IEnumerable<DataModel> dataModels)
{
//Assume a list of DataModels is in dataModels of type IEnumerable<DataModel>
var doc = new XmlDocument();
foreach (var model in dataModels)
{
var row = (XmlElement)doc.AppendChild(doc.CreateElement("row"));
row.SetAttribute("xmlns:od", "urn:schemas-microsoft-com:officedat");
row.SetAttribute("generated", DateTime.Now.ToString("yy-MM-ddTHH:mm:ss"));
var sifraElement = doc.CreateElement("Sifra");
sifraElement.InnerText = model.Sifra;
row.AppendChild(sifraElement);
//Repeat top 3 lines for each element ...
doc.AppendChild(row);
}
return doc.OuterXml;
}
Use XML Serializer :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication110
{
class Program
{
const string INPUT_FILENAME = #"c:\temp\test.xml";
const string OUTPUT_FILENAME = #"c:\temp\test1.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(INPUT_FILENAME);
string xml = reader.ToString();
XmlSerializer serializer = new XmlSerializer(typeof(DataRoot));
DataRoot root = (DataRoot)serializer.Deserialize(reader);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(OUTPUT_FILENAME,settings);
serializer.Serialize(writer, root);
}
}
[XmlRoot(ElementName = "dataroot", Namespace = "")]
public class DataRoot
{
[XmlElement(ElementName = "row", Namespace = "")]
public List<DataModel> rows { get; set; }
}
[XmlRoot(ElementName = "row", Namespace = "")]
public class DataModel
{
string Sifra { get; set; }
public string Naziv { get; set; }
public string JM { get; set; }
public int Kolicina { get; set; }
public float Cena_x0020_vp { get; set; }
public float Cena_x0020_mp { get; set; }
public float Cena_x0020_bod { get; set; }
public string Slika { get; set; }
public string Grupa { get; set; }
}
}
Related
C#:
XElement Xml = null;
var apiResponse = response.Content.ReadAsStringAsync().Result;
Xml = Newtonsoft.Json.JsonConvert.DeserializeObject<XElement>(apiResponse);
XML response from above code:
I'm having errors with Images xml part, while converting it to List,
I tried so many options, Please provide suggestion from below
<root>
<Column1>
<ID>2702</ID>
<Desc>Failed</Desc>
<Address>Florida</Address>
<Date>2019-04-30T23:10:36.79</Date>
<**Images**>
<Image>
<File>1-RRamos.PNG</File>
</Image>
<Image>
<File>RRamos.PNG</File>
</Image>
<Image>
<File>3-RRamos.PNG</File>
</Image>
</**Images**>
</Column1>
</root>
Trying to convert from xml to List from below
public class objClass
{
public string ID{ get; set; }
public string Desc{ get; set; }
public string Address { get; set; }
public DateTime? Date{ get; set; }
//public string[] ImageFileNames { get; set; }
public List<Images> FileName { get; set; }
}
public class FileName
{
public string File{ get; set; }
}
List<objClass> list = Xml.Elements("ID").Select(sv => new objClass()
{
ID= (string)sv.Element("ID"),
Desc= (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date= (DateTime?)sv.Element("Date"),
//**,Images = (List)sv.Element("Images")**
}).ToList();
From XML response, trying to convert it to List.
You can't use the Newtonsoft.Json library to deserialize from an XML.
Solution 1: Convert XML to list via XPath
Parse XML string to XDocument.
With XPath: "//root/Column1", select the <Column1> element.
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.XPath;
var apiResponse = await response.Content.ReadAsStringAsync();
XDocument #Xml = XDocument.Parse(apiResponse);
List<ObjClass> list = #Xml.XPathSelectElements("//root/Column1")
.Select(sv => new ObjClass()
{
ID = (string)sv.Element("ID"),
Desc = (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date = (DateTime?)sv.Element("Date"),
Images = sv.Element("Images")
.Elements("Image")
.Select(x => new Image
{
File = (string)x.Element("File")
})
.ToList()
})
.ToList();
Solution 2: Deserialize XML
This answer will be a bit complex but work the same as Solution 1.
Write the apiResponse value into MemoryStream.
Deserialize the MemoryStream via XmlSerializer as Root.
Extract root.Column and add into list.
[XmlRoot(ElementName = "root")]
public class Root
{
[XmlElement("Column 1")]
public ObjClass Column { get; set; }
}
public class ObjClass
{
public string ID { get; set; }
public string Desc { get; set; }
public string Address { get; set; }
public DateTime? Date { get; set; }
[XmlArray]
[XmlArrayItem(typeof(Image), ElementName = "Image")]
public List<Image> Images { get; set; }
}
public class Image
{
public string File { get; set; }
}
using System.Xml;
using System.Xml.Serialization;
using System.IO;
var apiResponse = await response.Content.ReadAsStringAsync();
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream);
writer.Write(apiResponse);
writer.Flush();
stream.Position = 0;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Root));
Root root = (Root)xmlSerializer.Deserialize(stream);
List<ObjClass> list = new List<ObjClass>();
list.Add(root.Column);
Concern:
Use await instead of Task<T>.Result as Task<T>.Result will block the calling thread until it (the task) is completed. With await, the task is waited to be completed asynchronously. Reference: What is the difference between await Task and Task.Result?
public class objClass
{
public string ID { get; set; }
public string Desc { get; set; }
public string Address { get; set; }
public DateTime? Date { get; set; }
public string[] ImageFileNames { get; set; }
}
var list = Xml.Elements("root").Elements("Column1")
.Select(sv => new objClass()
{
ID = (string)sv.Element("ID"),
Desc = (string)sv.Element("Desc"),
Address = (string)sv.Element("Address"),
Date = (DateTime?)sv.Element("Date"),
ImageFileNames = sv.Element("Images")
.Elements("Image")
.Select(i => (string)i.Element("File"))
.ToArray(),
})
.ToList();
I have a file .xml inside multiple xml in one line.
How can I read this file and convert to object?
I tried with this code it works if there is only one.
Please help and thank you all
[XmlRoot(ElementName = "DepartmentMaster")]
public class DepartmentMaster
{
[XmlElement(ElementName = "DepartmentId")]
public int DepartmentId { get; set; }
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Description")]
public string Description { get; set; }
[XmlElement(ElementName = "test")]
public int Test { get; set; }
}
//string xml = "<DepartmentMaster><DepartmentId>267854</DepartmentId><Name>Purchase</Name><Description>Purchase Department</Description><test>1</test></DepartmentMaster>";
string xml = "<DepartmentMaster><DepartmentId>267854</DepartmentId><Name>Purchase</Name><Description>Purchase Department</Description><test>1</test></DepartmentMaster><DepartmentMaster><DepartmentId>267855</DepartmentId><Name>Purchase5</Name><Description>Purchase Department5</Description><test>5</test></DepartmentMaster>";
using (TextReader reader = new StringReader(xml))
{
System.Xml.Serialization.XmlSerializer deserializer = new System.Xml.Serialization.XmlSerializer(typeof(DepartmentMaster));
var model = (DepartmentMaster)deserializer.Deserialize(reader);
}
image from the database
image from the database
Here it is two approaches below.
The first is using setting to accept XML data with multiple root elements (ConformanceLevel.Fragment).
private static IList<DepartmentMaster> DeserializeFragment(string xml)
{
var settings = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment
};
XmlReader reader = XmlReader.Create(new MemoryStream(Encoding.ASCII.GetBytes(xml)), settings);
var serializer = new XmlSerializer(typeof(DepartmentMaster));
var list = new List<DepartmentMaster>();
while (serializer.Deserialize(reader) is DepartmentMaster element)
{
list.Add(element);
}
return list;
}
And the second by adding a root element to deserialize a well-formed XML document.
public class DepartmentMasters
{
[XmlElement("DepartmentMaster")]
public List<DepartmentMaster> Items;
}
private static DepartmentMasters DeserializeWellFormedXML(string xml)
{
var text = #"<?xml version=""1.0""?><DepartmentMasters>" + xml + "</DepartmentMasters>";
var serializer = new XmlSerializer(typeof(DepartmentMasters));
return (DepartmentMasters)serializer.Deserialize(new StringReader(text));
}
Let's say I want to parse following XML file:
<EmployeeDetails>
<Employee> //List of Employees
<Id>11</Id>
<name>a</name>
<Dependents> //List of Dependents of a single employee
<Dependent>
<name>a1</name>
<age>50</age>
</Dependent>
<Dependent>
<name>a2</name>
<age>52</age>
</Dependent>
</Dependents>
<Department> //Unique per Emp
<DeptId>1</DeptId>
<DeptName>D1</DeptName>
</Department>
</Employee>
<Employee>
-----
--------
</Employee>
</EmployeeDetails>
Following is the Class Structure for above file:
public class Employee
{
public int id {get; set;}
public string name {get; set;}
public List<Dependents> Dependents {get; set;}
public Department Department {get; set;}
}
public class Dependents
{
public string name {get; set;}
public int age {get; set;}
}
public class Department
{
public int DeptId {get; set;}
public string DeptName {get; set;}
}
Now, I want to parse above XML structure and I am able to do it for id and name of Employee but I am unable to parse further.
Let me show you what I've done so far :
public static void ParseXml()
{
string xmldoc = //let's assume I've data in this string
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(xmldoc);
var query = from d in xdoc.Root.Descendants("Employee")
select d;
List<Employee> lsEmp = new List<Employee>();
foreach (var q in query)
{
Employee obj = new Employee();
obj.Id = Convert.ToInt32(q.Element("Id").Value);
obj.name = q.Element("name").Value;
obj.Department = new Department();
obj.Dependents = new List<Dependents>();
// how to get data further?
lsEmp.Add(obj);
}
So I need help in order to parse XML data from these list of Dependents and Department object.
Following your own structure, here's the way to continue parsing the data you need.
// how to get data further?
var allDependents = q.Elements("Dependents").Elements("Dependent");
foreach (var b in allDependents)
{
Dependents d = new Dependents
{
age = Convert.ToInt32(b.Element("age").Value),
name = b.Element("name").Value
};
obj.Dependents.Add(d);
}
obj.Department.DeptId = Convert.ToInt32(q.Element("Department").Element("DeptId").Value);
obj.Department.DeptName = q.Element("Department").Element("DeptName").Value;
Notice that I have used .Elements("") to get all the child nodes under Dependents
Here is code using just linq and no for loops
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
ParseXml(xml);
}
public static void ParseXml(string xml)
{
XDocument xdoc = XDocument.Parse(xml);
List<Employee> employees = xdoc.Descendants("Employee").Select(x => new Employee () {
id = (int)x.Element("Id"),
name = (string)x.Element("Name"),
Department = x.Elements("Department").Select(y => new Department() { DeptId = (int)y.Element("DeptId"), DeptName = (string)y.Element("DeptName")}).FirstOrDefault(),
Dependents = x.Descendants("Dependent").Select(y => new Dependents() { age = (int)y.Element("age"), name = (string)y.Element("name")}).ToList()
}).ToList();
}
}
public class Employee
{
public int id { get; set; }
public string name { get; set; }
public List<Dependents> Dependents { get; set; }
public Department Department { get; set; }
}
public class Dependents
{
public string name { get; set; }
public int age { get; set; }
}
public class Department
{
public int DeptId { get; set; }
public string DeptName { get; set; }
}
}
Maybe this can help you:
XDocument xdoc = new XDocument();
xdoc = XDocument.Parse(xmldoc);
var query = from d in xdoc.Root.Descendants("Employee")
select d;
List<Employee> lsEmp = new List<Employee>();
foreach (var q in query)
{
Employee obj = new Employee();
obj.Id = Convert.ToInt32(q.Element("Id").Value);
obj.name = q.Element("name").Value;
obj.Department = new Department()
{
DeptName = q.Element("Department").Element("name").Value,
DeptId =
Convert.ToInt32(q.Element("Department").Element("age").Value)
};
obj.Dependents = new List<Dependents>();
foreach (var e in q.Element("Dependents").Elements("Dependent"))
{
var dependent = new Dependents()
{
name = e.Element("name").Value,
age = Convert.ToInt32(e.Element("age").Value)
};
obj.Dependents.Add(dependent);
}
lsEmp.Add(obj);
}
How to get a namespace set at a child level element when serializing an object to XML with C#?
The XML I want to end up with this as the XML output:
<clsPerson>
<FirstName>Jeff</FirstName>
<MI>J</MI>
<LastName>Jefferson</LastName>
<ns1:Addresses xmlns="www.whatever.co.uk">
<Home>Here</Home>
<Work>There</Work>
</Addresses>
</clsPerson>
The code I'm using is mostly taken from other questions, and is as follows:
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
public class clsPerson
{
public string FirstName;
public string MI;
public string LastName;
[XmlElement(Namespace = "www.whatever.co.uk")]
public clsPlaces Addresses;
public clsPerson()
{
clsPlaces clsPlaces = new clsPlaces();
}
}
[XmlRoot(Namespace = "")]
public class clsPlaces
{
public string Home { get; set; }
public string Work { get; set; }
}
class class1
{
static void Main(string[] args)
{
clsPerson p = new clsPerson();
var xml = "";
p.FirstName = "Jeff";
p.MI = "J";
p.LastName = "Jefefrson";
p.Addresses = new clsPlaces();
p.Addresses.Home = "Here";
p.Addresses.Work = "There";
var emptyNamepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
var serializer = new XmlSerializer(p.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
emptyNamepsaces.Add("ns", "www.whatever.co.uk");
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, p, emptyNamepsaces);
xml = stream.ToString();
}
Console.WriteLine(xml)
Console.ReadLine();
}
}
The above gives:
<clsPerson xmlns:ns="www.whatever.co.uk">
<FirstName>Jeff</FirstName>
<MI>J</MI>
<LastName>Jefefrson</LastName>
<ns:Addresses>
<Home>Here</Home>
<Work>There</Work>
</ns:Addresses>
How would I get the xmlns on the element only? I have tried everything I can see search stackoverflow, and not been able to find/understand the answer.
Thanks
Remove this - adding the namespace will ensure the prefix gets added to the root:
emptyNamepsaces.Add("ns", "www.whatever.co.uk");
The declaration for addresses will get added automatically. You also need to remove the empty namespace from clsPlaces, else the namspaces for Home and Work will be incorrect:
public class clsPlaces
{
public string Home { get; set; }
public string Work { get; set; }
}
The output will then look like this:
<clsPerson>
<FirstName>Jeff</FirstName>
<MI>J</MI>
<LastName>Jefefrson</LastName>
<Addresses xmlns="www.whatever.co.uk">
<Home>Here</Home>
<Work>There</Work>
</Addresses>
</clsPerson>
See this fiddle for a demo.
I have an xml file which is in this format
"<rundate>
<rundateItem>
<LeaveCreditingMonth>2</LeaveCreditingMonth>
<LeaveCreditingYear>2010</LeaveCreditingYear>
<IncludeNoTimesheet>True</IncludeNoTimesheet>
</rundateItem>
</rundate>"
in case i want to deserialize this xml file, what should be the format of the class or the target object of my deserialization?
Currently my class looks like this:
public class rundate
{
string _leaveCreditingMonth;
string _leaveCreditingYear;
string _includeNoTimesheet;
public string LeaveCreditingMonth {get{return _leaveCreditingMonth;}set{ _leaveCreditingMonth = value;}}
public string LeaveCreditingYear {get{return _leaveCreditingYear;}set{ _leaveCreditingYear = value;}}
public string IncludeNoTimesheet {get{return _includeNoTimesheet;}set{ _includeNoTimesheet = value;}}
}
Your class can stay as is (obviously you should change the data types to be appropriate though) - since you have rundate nested in your XML (which implies there can be more than one) I would suggest adding a collection class as follows:
[XmlRoot("rundate")]
public class RundateCollection
{
[XmlElement("rundateItem")]
public List<rundate> Rundates { get; set; }
}
You can test serializing/deserializing your class with your XML as follows:
XmlSerializer serializer = new XmlSerializer(typeof(RundateCollection));
StringWriter sw = new StringWriter();
rundate myRunDate = new rundate() { LeaveCreditingMonth = "A", IncludeNoTimesheet = "B", LeaveCreditingYear = "C" };
RundateCollection ra = new RundateCollection() { Rundates = new List<rundate>() { myRunDate } };
serializer.Serialize(sw, ra);
string xmlSerialized = sw.GetStringBuilder().ToString();
string xml = File.ReadAllText(#"test.xml");
StringReader sr = new StringReader(xml);
var rundateCollection = serializer.Deserialize(sr);
You will see that the collection class is successfully deserialized from your XML and contains one list item of type runlist.
I would design the class like so:
public class Rundate
{
public int LeaveCreditingMonth { get; set;}
public int LeaveCreditingYear { get; set; }
public bool IncludeNoTimesheet { get; set; }
}
Then you can deserialize it like this:
var serializer = new XmlSerializer(typeof(List<Rundate>));
using (var fs = new FileStream("yourfile.xml", FileMode.Open))
{
using (var reader = new XmlTextReader(fs))
{
var rundates = (List<Rundate>)serializer.Deserialize(reader);
}
}