I need to deserialize XML into one simple array of objects, but can't quite figure out how to do it. Here is my simplified XML:
<?xml version="1.0" encoding="Windows-1250"?>
<document>
<datasets>
<dataset0>
<rows>
<row>
<fields>
<id>1</id>
<name>Cat1</name>
</fields>
</row>
<row>
<fields>
<id>2</id>
<name>Cat2</name>
</fields>
</row>
</rows>
</dataset0>
</datasets>
</document>
I've created class for the object to deserialize into
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
And the deserialization code
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Category[]), new XmlRootAttribute("rows"));
using (FileStream myFileStream = categoryFile.OpenRead())
{
var categoryArray = (Category[])xmlSerializer.Deserialize(myFileStream);
}
This obviously doesn't work, I've tried various XmlElement and XmlRoot tags, but I don't quite know what I'm doing so I stripped all that out to avoid public embarrassment. Thanks for any input.
It seems that, the object which you want to deserialize doesn't have exact compatibility with your xml file. So, in this case it could be more flexible to use Linq to xml solution.
var xDocument = XDocument.Parse(xml);
var categoryList = xDocument.Descendants("fields").Select(x => new Category
{
Name = x.Element("name").Value,
Id = int.Parse(x.Element("id").Value)
});
Related
I have the problem that I got xml from a REST service and have to deserialize it to an object structure and there is a type="proglang" in it.
<listResult>
<listEntry xsi:type="proglang">
<id>0</id>
<name>C#</name>
</listEntry>
<listEntry xsi:type="proglang">
<id>0</id>
<name>C#</name>
</listEntry>
</listResult>
How should the object model with the xml attributes look like in c#?
My Code so far:
[XmlRoot("listResult")]
public class ListResult
{
[XmlElement("listEntry")]
//[XmlArrayItem(Type=typeof(proglang))]
public List<proglang> listEntry;
}
public class proglang
{
[XmlElement("code")]
public int id;
[XmlElement("label")]
public string name;
}
and the resulting XML from serializing:
<listResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<listEntry>
<code>1</code>
<label>C#</label>
</listEntry>
<listEntry>
<code>1</code>
<label>C++</label>
</listEntry>
</listResult>
Hi I have a Web Service that feeds my application with the following XML:
<Value><TABLE>
<PRODUCT>
<ProductID> 1 </ProductID>
<Category> sport </Category>
<Description> calcio </Description>
<Name> palla </Name>
<Price> 10 </Price>
</PRODUCT>
<PRODUCT>
<ProductID> 2 </ProductID>
<Category> sport </Category>
<Description> tennis </Description>
<Name> racchetta </Name>
<Price> 100 </Price>
</PRODUCT>
<PRODUCT>
<ProductID> 3 </ProductID>
<Category> sport </Category>
<Description> golf </Description>
<Name> borsa </Name>
<Price> 150 </Price>
</PRODUCT>
</TABLE></Value>
I wrote the following object models and I manage to deserialize correcly using XmlSerializer.
[XmlRoot("Value")]
public class Value {
[XmlElement("TABLE")]
public TABLE TABLE { get; set; }
}
public class TABLE {
[XmlElement("PRODUCT")]
public List<Product> Products { get; set; }
}
public class Product {
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Category { get; set; }
public int Price { get; set; }
}
Now, I eventually add new Product objects and I want to serialize the model into and XML in order to sending it back to the web service. The problem is that the XML structure accepted is slighty different, I'd want the XML structure to be like this:
<setProdotti>
<streams>
<instream>
<Value><TABLE>
<PRODUCT>
<ProductID> 1 </ProductID>
<Category> sport </Category>
<Description> calcio </Description>
<Name> palla </Name>
<Price> 10 </Price>
</PRODUCT>
</TABLE></Value>
</instream>
</streams>
</setProdotti>
Basically the same as the input XML with the exception of the embedding tags setProdotti, streams and instream, which are fixed and known (can be hardcoded).
Can it be done with the current model? I tryed to use XmlSerializer's Serialize method but id output an XML based on the model (of course) and with tags on the root elements that I'd like to avoid too.
<?xml version="1.0" encoding="utf-16"?><Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TABLE>
<PRODUCT><ProductID>1</ProductID><Name> palla </Name><Description> nike </Description><Category> calcio </Category><Price>10</Price></PRODUCT>
</TABLE>
</Value>
Thanks for your help.
Following the advice of Alexander Petrov, I looked into detail the XmlWriter
The resulting code that satisfy my requirements is:
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
XmlSerializer xmlserializer = new XmlSerializer(typeof(Value));
StringWriter stringWriter = new StringWriter();
XmlWriter writer2 = XmlWriter.Create(stringWriter, new XmlWriterSettings {
OmitXmlDeclaration = true,
ConformanceLevel = ConformanceLevel.Fragment
});
writer2.WriteStartElement("setProdotti");
writer2.WriteStartElement("streams");
writer2.WriteStartElement("instream");
xmlserializer.Serialize(writer2, p, ns);
writer2.Dispose();
string serializedXml = stringWriter.ToString();
The part about XmlSerializerNamespacesavoid the creation of XML attributes on the Value element (p) and i set up XmlWriterSetting so that I have no XML declaration at the beginning of the string.
Apparently .Dispose() closes the tags I opened with .WriteStartElement. I was looking for the .Close() method but it doesn't exist anymore.
I am trying to Deserialize an xml file that looks like the following
<?xml version="1.0"?>
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication6">
<values>
<String>Value 1</String>
<String>Value 2</String>
</values>
</Test>
to an object that is this
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/ConsoleApplication6")]
public class Test
{
[DataMember(Name = "values")]
public String[] values;
}
with
var ds = new DataContractSerializer(typeof(Test));
using (Stream stream1 = File.OpenRead(#"C:\Projects\test1.xml"))
{
Test rr = (Test)ds.ReadObject(stream1);
}
However none of the values are deserializing. I just see and empty array in Test rr. Could you please tell what I am doing wrong. Thanks in advance.
If you need fine control of the XML that is emitted when serializing, you should not use DataContractSerializer. It is has very limited flexibility. You would be better off using XmlSerializer, which has liimtitations as well, but is much more flexible than DataContractSerializer.
That being said, here is how you can do what you want with DataContractSerializer.
Change the default namespace on your xml to use the one that DataContractSerializeruses by default.
<?xml version="1.0"?>
<Test xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/">
<values>
<String>Value 1</String>
<String>Value 2</String>
</values>
</Test>
Instead of using string[] create your own custom type that derives from List<string>. This must be done solely for the purpose of having something to hang CollectionDataContractAttribute on. CollectionDataContractAttribute is what will let you specify the name of the elements inside <values>.
[DataContract]
public class Test
{
[DataMember(Name = "values")]
public TestValues values;
}
[CollectionDataContract(ItemName = "String")]
public class TestValues : List<string> { }
The DataContractSerializer has its own rules for XML and cannot support all XML forms. I suggest using the XmlSerializer.
Use this definition
[XmlClass(Namespace = "http://schemas.datacontract.org/2004/07/ConsoleApplication6")]
public class Test
{
[XmlArray("values")]
[XmlArrayItem("String")]
public String[] values;
}
I'm working on google product feed xml with C#
I can generate a xml with using XmlSerializer but I can't solve just one problem;
In xml feed example, product id has to be like this;
...
<item>
<title>Super item</title>
<link>http://www.bla.com/13007/2202170/</link>
<description>Test description</description>
<g:id>1234678</g:id>
</item>
...
But as you can see special " : " char in xml element tag.
So when I write "[XmlElement("g:id")]" on my property like;
[DataMember]
[XmlElement("g:id")]
public int Id { get; set; }
XmlSerializer generetad my xml tag like; < g_X003A_id >
And generated xml looking like this;
...
<item>
<title>Super item</title>
<link>http://www.bla.com/13007/2202170/</link>
<description>Test description</description>
<g_X003A_id>1234678</g_X003A_id>
</item>
...
How can I solve this problem ?
I solved this problem like;
[DataMember]
[XmlElement("id", Namespace = "http://base.google.com/ns/1.0")] //g:id
public int Id { get; set; }
I'm trying to deserialize an xml file to a .NET object by doing something like:
CarCollection myCarCollection = null;
string path = "CarCollection.xml";
XmlSerializer serializer = new XmlSerializer(typeof(CarCollection));
StreamReader reader = new StreamReader(path);
myCarCollection= (CarCollection)serializer.Deserialize(reader);
reader.Close();
Here is the xml file I'm using:
<?xml version="1.0" encoding="utf-8" ?>
<CarCollection>
<Car ID="A">
<CarType Make="Ford" Model="Focus" />
<CarOwner Name="Tom">
<Report Type="Service">
<ReportList>
<Date>20-08-2010</Date>
</ReportList>
</Report>
</CarOwner>
</Car>
<Car ID="B">
<CarType Make="Vauxhall " Model="Corsa" />
<CarOwner Name="Joe">
<Report Type="Service">
<ReportList>
<Date>10-10-2008</Date>
<Date>10-10-2009</Date>
<Date>10-10-2010</Date>
</ReportList>
</Report>
<Report Type="Accident">
<ReportList>
<Date>20-01-2011</Date>
</ReportList>
</Report>
</CarOwner>
</Car>
</CarCollection>
I've tried many things but can't seem to get it working.
Could anyone please help me how to do deserialize to a .NET object.
Here is the C# Objects
[Serializable()]
[XmlRoot("CarCollection")]
public class CarCollection
{
[XmlArray("Car")]
[XmlArrayItem("Car", typeof(Car))]
public Car[] Cars { get; set; }
}
[Serializable()]
public class Car
{
[XmlAttribute("Make")]
public string CarMakeType { get; set; }
[XmlAttribute("Model")]
public string CarModelType { get; set; }
[XmlArray("CarOwner")]
[XmlArrayItem("CarOwner", typeof(CarOwner))]
public CarOwner[] CarOwners { get; set; }
}
[Serializable()]
public class CarOwner
{
[XmlAttribute("Name")]
public string Name { get; set; }
[XmlArray("Report")]
[XmlArrayItem("Report", typeof(Report))]
public Report[] Reports { get; set; }
}
[Serializable()]
public class Report
{
[XmlAttribute("Type")]
public string Type { get; set; }
[XmlArray("Report")]
[XmlArrayItem("Report", typeof(DateTime))]
public DateTime[] Reports { get; set; }
}
Tangentially you might find some benefit in using XSD to generate XML from your classes.
I bet this is due to the date format.
the xmlns declaration is also missing.
The Felice suggestion is a good one. Try to produce the desired result with serializing, before trying to deserialize
Read this page in the MSDN to verify your code.
The yellow note halfway down the page specifies what requirements must be met by collections.
Also: pass the Car type too, to the Serializer constructor.
EDIT
The Report and Car tags are not closed!
EDIT
Here is the output when serializing. Spot the differences there are many. The biggest problem is how you are serializing the arrays. Start using plurals (Cars, Owners) for collections that wil make it more readable.
<?xml version="1.0" encoding="utf-8"?>
<CarCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Car>
<Car Make="make">
<CarOwner>
<CarOwner Name="name1">
<Report>
<Report Type="rtype">
<Report>
<Report>2011-01-25T15:22:52.703125+01:00</Report>
</Report>
</Report>
</Report>
</CarOwner>
</CarOwner>
</Car>
<Car Make="make2">
<CarOwner>
<CarOwner Name="name3">
<Report>
<Report Type="rtype">
<Report>
<Report>2011-01-25T15:22:52.703125+01:00</Report>
</Report>
</Report>
</Report>
</CarOwner>
</CarOwner>
</Car>
</Car>