C# .Net - write data in xml by using existing structure/schema - c#

I have an API which creates a sample xml based on a schema file. Here is the link to the API: http://msdn.microsoft.com/en-us/library/aa302296.aspx
Now, suppose the sample xml generated is as follows:
<Employee>
<Name>Bond</Name>
<Address>abc,unknown street</Address>
<phone>0000000000</phone>
<Employee>
I have a employee DB table consisting of thousands of employee records. What I want is to write those records in the xml format created above (table has many non-required columns also so can't use dataset.writexml).
What is the right approach of doing this ? Should I edit the first node as per the first record and then copy the whole node into same xml, write the record then repeat the process till end of records? Or is there a better approach of doing this?

Here is an example of serializing and Deserializing Objects to xml.
using System;
using System.Xml.Serialization;
using System.IO;
namespace Test
{
[Serializable]
[XmlRoot("DocumentElement")]
public class Documentelement
{
[XmlElement]
public PartInfo[] PartInfo { get; set; }
}
public class PartInfo
{
[XmlElement]
public int ID { get; set; }
public string Name { get; set; }
public string PartNo { get; set; }
public int SerialNo { get; set; }
public string Parameter { get; set; }
public DateTime InstallDate { get; set; }
public DateTime InstallTill { get; set; }
}
public class Test
{
private PartInfo details_1()
{
PartInfo details = new PartInfo
{
ID = 0,
Name = "QVR",
PartNo = "A11",
SerialNo = 453,
Parameter = "C -11",
// This you should add as date time, I just used the string to parse your time that you showed in your example.
InstallDate = DateTime.Parse("2013-02-04T17:16:56.383+05:30"),
InstallTill = DateTime.Parse("2013-02-15T17:16:56.3830837+05:30")
};
return details;
}
private PartInfo details_2()
{
PartInfo details = new PartInfo
{
ID = 1,
Name = "EAFR",
PartNo = "B07",
SerialNo = 32,
Parameter = "B-16",
// This you should add as date time, I just used the string to parse your time that you showed in your example.
InstallDate = DateTime.Parse("2013-02-18T17:17:44.589+05:30"),
InstallTill = DateTime.Parse("2013-02-28T17:17:44.589+05:30")
};
return details;
}
public void setXmlValues()
{
Documentelement testOut = new Documentelement { PartInfo = new[] { details_1(), details_2() }};
xml_serialise(testOut);
Documentelement testIn = xml_deserialise();
int val = testIn.PartInfo[0].ID;
DateTime dt = testIn.PartInfo[0].InstallDate;
string shortTime = dt.ToShortTimeString();
}
private void xml_serialise(Documentelement test)
{
XmlSerializer ser = new XmlSerializer(typeof(Documentelement));
using (TextWriter writer = new StreamWriter("test.xml"))
{
ser.Serialize(writer, test);
}
}
private Documentelement xml_deserialise()
{
XmlSerializer ser = new XmlSerializer(typeof(Documentelement));
Documentelement test;
using (TextReader writer = new StreamReader("test.xml"))
{
test = (Documentelement)ser.Deserialize(writer);
}
return test;
}
}
}

One approach could be to use xsd.exe (one of the VS command-line tools) to generate a schema from the sample XML, and then use xsd.exe with the schema to generate a C# class. This class is ready to use with serialization, so you could convert your data into a List<GeneratedClass> and then serialize it. Not saying it's the best approach, but I've used it before successfully.

Related

c# parse string to xml using StringReader

I have an XML and I load it in an class.
This is my XML
<out_policySystem xmlns:msl="http://www.ibm.com/xmlmap" xmlns:io="" xmlns:xs4xs="http://www.w3.org/2001/XMLSchema">
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
</out_policySystem>
I have define my classes like this.
[XmlRoot(ElementName = "out_policySystem")]
public partial class output_policySystem
{
public BGBAResultadoOperacion BGBAResultadoOperacion { get; set; }
public bool permiteOperar { get; set; }
public List[] Lista { get; set; }
}
public partial class BGBAResultadoOperacion
{
public string Severidad { get; set; }
}
public partial class List
{
public string Codigo { get; set; }
public string Descripcion { get; set; }
public string DescripcionTecnica { get; set; }
}
I read this like this.
XmlNodeList elemlist = xDoc.GetElementsByTagName("out_policySystem");
string result = elemlist[0].InnerXml;
XmlSerializer serializer = new XmlSerializer(typeof(BGBAResultadoOperacion));
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
the value of result is this.
<BGBAResultadoOperacion><Severidad>OK</Severidad></BGBAResultadoOperacion><permiteOperar>true</permiteOperar><Lista><Codigo>ODM-006</Codigo><Descripcion>Aviso</Descripcion><DescripcionTecnica>xxxx</DescripcionTecnica></Lista>
What I need is to get the value of BGBAResultadoOperacion
when i set
using (StringReader reader = new StringReader(result))
{
result = (BGBAResultadoOperacion)(serializer.Deserialize(reader));
}
result get XML error...
There are multiple root elements. Line 1, position 76.
XML node out_policySystem has three root elements inside it. I need to parse only BGBAResultadoOperacion
How can I get it?
Thanks
That's because of this line:
elemlist[0].InnerXml
Which returns an XML Fragment, not an XML Document.
<BGBAResultadoOperacion>
<Severidad>OK</Severidad>
</BGBAResultadoOperacion>
<permiteOperar>true</permiteOperar>
<Lista xmlns:ns0=\"http://CalypsoPolicySystem_lib/service\">
<Codigo>ODM-006</Codigo>
<Descripcion>Aviso</Descripcion>
<DescripcionTecnica>XXXX</DescripcionTecnica>
</Lista>
So either use the .OuterXML, or use XElement.CreateReader() as described in the answer here: Serialize an object to XElement and Deserialize it in memory

C# Deserialze XML to an Object

I am trying to deserialize xml to an object using C#.
This is my XML.
<Products>
<Product>
<Name>Test</Name>
<Price Amount="12.95">£ 12.95</Price>
</Product>
</Products>
And this is my code.
class Program
{
static void Main(string[] args)
{
var filePath = #"C:\Eastpoint\TestApps\TestHunterSuppliers\bin\Debug\Sample.xml";
var reader = new XmlTextReader(filePath);
var serializer = new XmlSerializer(typeof(Products));
var products = (Products)serializer.Deserialize(reader);
Console.WriteLine(products.Product.Name);
Console.WriteLine(products.Product.Price.Amount);
}
}
public class Products
{
public Product Product { get; set; }
}
public class Product
{
public string Name { get; set; }
public Price Price { get; set; }
}
public class Price
{
public string Amount { get; set; }
public string Value { get; set; }
}
By using the above code I am getting the product object but properties of the price object are always deserializing to null values.
Could somebody advice me what I am missing.
Thanks,
Naresh
The default behavior of .NET's XML serializer is to serialize properties to XML elements. The value of the property becomes the inner text of the XML element corresponding to the property. That is, if you serialized your objects it would look like this:
<Products>
<Product>
<Name>Test</Name>
<Price>
<Amount>12.95</Amount>
<Value>£ 12.95</Value>
</Price>
</Product>
</Products>
In your case, you need to instruct the serializer to put Price.Amount into an attribute and to write Price.Value as Price's inner text. The easiest way to do this is to decorate the properties requiring non-default serialization with appropriate [XmlXxx] attributes:
...
[XmlAttribute]
public string Amount { get ; set ; }
[XmlText]
public string Value { get ; set ; }
...
Incidentally, if your Products is supposed to contain more than one product, you will need to modify your code like this:
...
[XmlElement ("Product")]
public Product[] All { get ; set ; }
...
The attribute instructs the serializer not to create an <All> element to hold the individual products' elements. You can also use other collections like List<Product>, but you should create them beforehand like this:
...
[XmlElement ("Product")]
public readonly List<Product> All = new List<Product> () ;
...
You can make your original test code working using FileStream,
Tested code sample:
var filePath = #"C:\Eastpoint\TestApps\TestHunterSuppliers\bin\Debug\Sample.xml";
var serializer = new XmlSerializer(typeof(Products));
//Setting dummy object to create the xml
Products myProducts = new Products { Product = new Product { Name = "Papers", Price = new Price { Amount = "10", Value = "20" } } };
var strWrite = new FileStream(filePath, FileMode.Create);
serializer.Serialize(strWrite, myProducts);
strWrite.Close();
//////////////////////////////
var strRead = new FileStream(filePath, FileMode.Open);
var products = (Products)serializer.Deserialize(strRead);
strRead.Close();
Console.WriteLine(products.Product.Name);
Console.WriteLine(products.Product.Price.Amount);
And to get the price as an attribute in the XML document:
public class Price
{
[XmlAttribute]
public string Amount { get; set; }
public string Value { get; set; }
}

Extracting Data From XML File Using C#

I have some XML file sitting in my /bin folder (using vs2010). I would like to extract some data (attributes, element values) from this xml. What is the best way to do this using C#?
do I need to use XMLTextReader or would it be better to create an xmlDocument...I'm confused...
You could use LINQ to XML ?
http://msdn.microsoft.com/en-us/library/bb387098.aspx
Either System.Xml og System.Linq.Xml
I would recommend Linq2Xml: http://msdn.microsoft.com/en-us/library/bb387098.aspx
This is a good guide: http://www.hookedonlinq.com/LINQtoXML5MinuteOverview.ashx
Here is a simple example of querying an XML File
public class Job
{
public int Id { get; set; }
public int CompanyId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int HoursPerWeek { get; set; }
}
Snippet of XML File:
<?xml version="1.0" encoding="utf-8"?>
<Jobs>
<Job>
<Id>1</Id>
<CompanyId>2</CompanyId>
<Description>Must be willing to relocate to Nebraska.</Description>
<HoursPerWeek>90</HoursPerWeek>
<JobStatus>1</JobStatus>
<JobType>3</JobType>
<Location>NY</Location>
<Title>Application Engineer for Gooooogle Plus</Title>
</Job>
<Job>
Class which populates Job objects from XML File
public class XMLJobsDAL
{
XDocument JobDoc
{
get { return XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/Job.xml")); }
}
public List<Job> GetJobs()
{
var results = from job in JobDoc.Descendants("Job")
select new Job
{
Id = (int)job.Element("Id"),
CompanyId = (int)job.Element("CompanyId"),
Description = (string)job.Element("Description"),
HoursPerWeek = (int)job.Element("HoursPerWeek"),
Title = (string) job.Element("Title")
}
return results.ToList();
}
public Job GetJob(int id)
{
var result = from job in JobDoc.Descendants("Job")
where (int)job.Element("Id") == id
select new Job
{
Id = (int)job.Element("Id"),
CompanyId = (int)job.Element("CompanyId"),
Description = (string)job.Element("Description"),
HoursPerWeek = (int)job.Element("HoursPerWeek"),
Title = (string) job.Element("Title")
}
return result.SingleOrDefault();
}
}
I would recommend that you check Serialization out. Here is a little example of how to Serialize/Deserialize XML to/from an object using ek_ny XML Document:
using System.IO;
using System.Xml.Serialization;
[Serializable]
public class Job
{
public Job() { }
public int ID { get; set; }
public int CompanyID { get; set; }
public string Description { get; set; }
public int HoursPerWeek { get; set; }
public int JobStatus { get; set; }
public int JobType { get; set; }
public string Location { get; set; }
public string Title { get; set; }
public void SerializeToXML(string path)
{
//creates a file
FileStream fs = new FileStream(path, FileMode.Create);
//now we create the serializer
XmlSerializer xs = new XmlSerializer(typeof(Job));
//serialize it to the file
xs.Serialize(fs, this);
//close the file
fs.Close();
}
public static Job DeserializeToJob(string path) {
//open file
FileStream fs = new FileStream(path, FileMode.Open);
//create deserializer
XmlSerializer xs = new XmlSerializer(typeof(Job));
//Deserialize
Job job = (Job)xs.Deserialize(fs);
//close the file
fs.Close();
//return the deserialized job
return job;
}
}
Implementation:
class Program
{
static void Main(string[] args)
{
Job j = new Job();
j.CompanyID = 2;
j.ID = 1;
j.Description = "Must be willing to relocate to Nebraska.";
j.HoursPerWeek = 90;
j.JobStatus = 1;
j.JobType = 3;
j.Location = "NY";
j.Title = "Application Engineer for Gooooogle Plus";
//Saving the object serialized.
j.SerializeToXML("MyJob.xml");
//deserialize the saved job into a new instance
Job j2 = Job.DeserializeToJob("MyJob.xml");
}
}
With this you will get the object back and forth from and to XML. This is what has worked the best for me. The only cons I can see here is that if your XML document has a lot of properties you will have to make a very big class.
http://support.microsoft.com/kb/815813
http://www.switchonthecode.com/tutorials/csharp-tutorial-xml-serialization
Good luck!
There's one good way to do this. You can use
DataTable.ReadXml(string fileName)
it takes care of everything easily. Depending on the problem, it could be useful or not.
Note this methods cannot get the schema from xml file, you should add columns to the table yourself.

XML Serialization on .NET for Oracle .insertxml

I've been studying up and prepping serialization of class objects. The purpose of my code is to pass a json string to a WCF that is stored in the following class object:
[XmlRoot("ROWSET")]
public class Person
{
[XmlElement("FIRST_NAME")]
public string first_name { get; set; }
[XmlElement("MIDDLE_NAME")]
public string middle_name { get; set; }
[XmlElement("LAST_NAME")]
public string last_name { get; set; }
}
Simple so far. Next, i have a code in place to serialize the object into XML and strip out the headerinformation in preparation to send the XML string to be passed to Oracle as a CLOB and then stored in a table. This is the result:
<ROWSET>
<FIRST_NAME>John</FIRST_NAME>
<MIDDLE_NAME>James</MIDDLE_NAME>
<LAST_NAME>Smith</LAST_NAME>
</ROWSET>
Now - that looks ready to send to Oracle to be inserted to a table. The problem is, I need to send it as Oracle XML format - known as Oracle Canonical format - which should be as:
<ROWSET>
**<ROW>**
<FIRST_NAME>John</FIRST_NAME>
<MIDDLE_NAME>James</MIDDLE_NAME>
<LAST_NAME>Smith</LAST_NAME>
**</ROW>**
</ROWSET>"
I'm trying to understand serialize to a point where I want to insert between the column data. Has anyone some something similar?
thanks,
Glenn
I would shape the DTO accordingly:
[XmlRoot("ROWSET")]
public class PersonRowSet
{
[XmlElement("ROW")]
public Person Item {get;set;}
// ^^^ could perhaps be public List<Person> Items {get;set;}
}
public class Person
{
[XmlElement("FIRST_NAME")]
public string first_name { get; set; }
[XmlElement("MIDDLE_NAME")]
public string middle_name { get; set; }
[XmlElement("LAST_NAME")]
public string last_name { get; set; }
}
Also note that you shouldn't need to "strip out" the header junk - if you configure the writer correctly it won't be added in the first place:
using (var sw = new StringWriter())
{
using (var xw = XmlWriter.Create(sw, new XmlWriterSettings {
OmitXmlDeclaration = true }))
{
var obj = new PersonRowSet
{
Item = new Person
{
first_name = "John",
last_name = "Smith",
middle_name = "James"
}
};
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var ser = new XmlSerializer(typeof(PersonRowSet));
ser.Serialize(xw, obj, ns);
}
string xml = sw.ToString();
}

What is the best way to manually parse an XElement into custom objects?

I have an XElement variable named content which consists of the following XML:
<content>
<title>Contact Data</title>
<p>This is a paragraph this will be displayed in front of the first form.</p>
<form idCode="contactData" query="limit 10; category=internal"/>
<form idCode="contactDataDetail" query="limit 10; category=internal">
<title>Contact Data Detail</title>
<description>This is the detail information</description>
</form>
</content>
I now want to simply run through each of the level-1 nodes and parse them into objects. Back in C# 2.0 I use to do this with XmlReader, check the type of node, and parse it accordingly.
But what is the best way to parse the XML nodes with LINQ, I would expect something like this:
var contentItems = from contentItem in pageItem.content.DescendantNodes()
select new ContentItem
{
Type = contentItem.Element()
};
foreach (var contentItem in contentItems)
{
switch (contentItem.Type)
{
case "title":
...(parse title)...
case "p":
...(parse p)...
case "form":
...(parse form)...
}
}
where:
public class ContentItem
{
public string Type { get; set; }
public string IdCode { get; set; }
public XElement Content { get; set; }
}
Does it have to be XElement? I would (either manually, or via xsd.exe) just create classes that map to the element/attribute names - and use XmlSerializer - in particular via StringReader:
Content content;
using(StringReader sr = new StringReader(xml))
using(XmlReader xr = XmlReader.Create(sr)) {
XmlSerializer ser = new XmlSerializer(typeof(Content));
content = (Content)ser.Deserialize(xr);
}
(edit)
With entity classes:
[XmlRoot("content")]
public class Content {
[XmlElement("title")]
public string Title { get; set; }
[XmlElement("p")]
public string Description { get; set; }
[XmlElement("form")]
public List<ContentForm> Forms { get; set; }
}
public class ContentForm {
[XmlAttribute("idCode")]
public string Id { get; set; }
[XmlAttribute("query")]
public string Query { get; set; }
[XmlElement("title")]
public string Title { get; set; }
[XmlElement("description")]
public string Description { get; set; }
}
I'd suggest inheriting XElement, and implement properties for the stuff you want in it.
These properties shouldn't use backing fields, but rather work directly with the underlying XML element. That way, you'll keep object in sync with XML.
With XML to LINQ one pulls specific data items out of the XML, rather than iterating through the XML looking for what is found.
var results = from node in XmlDocument.SomeContext(...)
select new MyType {
Prop1 = node.Element("One").Value,
Prop2 = node.Element("One").Attributes().Where(
a => A.Value.Contains("Foo").Value
};
If conditions are needed, then (extension) methods and arbitrary expressions can be used (null-coalescing operator, ??, can be very helpful to default).

Categories

Resources