Cannot deserialize from XML - c#

I have a fixed, valid XML document. I'm trying to deserialize it in order to get an object hierarchy. However there's an exception being thrown.
This is my XML document:
<ROWSET>
<ROW>
<LOT>LOT1234</LOT>
<DATE_TRANS>2012-05-20</DATE_TRANS>
<NUMERO_AA227>AA227_001</NUMERO_AA227>
<NUMERO_ETUI>ETUI_001</NUMERO_ETUI>
<IDENTITE_BOITE_1>Boite1_1</IDENTITE_BOITE_1>
<IDENTITE_BOITE_2>Boite1_2</IDENTITE_BOITE_2>
<IDENTITE_BOITE_3>Boite1_3</IDENTITE_BOITE_3>
<IDENTITE_BOITE_4>Boite1_5</IDENTITE_BOITE_4>
<IDENTITE_BOITE_5>Boite1_5</IDENTITE_BOITE_5>
</ROW>
<ROW>
<LOT>LOT5678</LOT>
<DATE_TRANS>2012-05-20</DATE_TRANS>
<NUMERO_AA227>AA227_001</NUMERO_AA227>
<NUMERO_ETUI>ETUI_001</NUMERO_ETUI>
<IDENTITE_BOITE_1>Boite1_1</IDENTITE_BOITE_1>
<IDENTITE_BOITE_2>Boite1_2</IDENTITE_BOITE_2>
<IDENTITE_BOITE_3>Boite1_3</IDENTITE_BOITE_3>
<IDENTITE_BOITE_4>Boite1_5</IDENTITE_BOITE_4>
<IDENTITE_BOITE_5>Boite1_5</IDENTITE_BOITE_5>
</ROW>
</ROWSET>
And this is my object model:
[Serializable]
[System.Xml.Serialization.XmlRoot("DTOFournitureListeImporter")]
public class DTOFournitureListeImporter
{
[XmlArray("ROWSET")]
[XmlArrayItem("ROW", typeof(DTOFournitureImporter))]
public DTOFournitureImporter[] dtoFournitureImporter { get; set; }
}
[Serializable]
public class DTOFournitureImporter
{
[System.Xml.Serialization.XmlElement("lot")]
public string lot { get; set; }
[System.Xml.Serialization.XmlElement("date_trans")]
public DateTime date_trans { get; set; }
[System.Xml.Serialization.XmlElement("numero_aa227")]
public string numero_aa227 { get; set; }
[System.Xml.Serialization.XmlElement("numero_etui")]
public string numero_etui { get; set; }
[System.Xml.Serialization.XmlElement("identite_boite_1")]
public string identite_boite_1 { get; set; }
[System.Xml.Serialization.XmlElement("identite_boite_2")]
public string identite_boite_2 { get; set; }
[System.Xml.Serialization.XmlElement("identite_boite_3")]
public string identite_boite_3 { get; set; }
[System.Xml.Serialization.XmlElement("identite_boite_4")]
public string identite_boite_4 { get; set; }
[System.Xml.Serialization.XmlElement("identite_boite_5")]
public string identite_boite_5 { get; set; }
}
How I deserialize:
XmlSerializer serializer = new XmlSerializer(typeof(DTOFournitureListeImporter));
TextReader textReader = new StreamReader(model.cheminFichierXML);
DTOFournitureListeImporter dTOFournitureListeImporter = (DTOFournitureListeImporter)serializer.Deserialize(textReader);
textReader.Close();
And the error:
There is an error in XML document (2, 2). -
System.InvalidOperationException: was not expected.
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDTOFournitureListeImporter.Read4_DTOFournitureListeImporter()

The problem could be that all the tags in the XML file are in capital letters, but the attributes in your class suggest they should be in small letters.
Also, you're saying in the attributes that the XML root is DTOFournitureListeImporter, which is not the case. The XML root is ROWSET.
So all in all: The structure you're trying to create does not match the XML file.

Related

Serializing object to xml with multiple equal tag names

This is the list I want serialized to xml:
public class LocationViewModel
{
[XmlElement("cell", Order = 1)]
public int Id { get; set; }
[XmlElement("cell2", Order = 2)]
public string Name { get; set; }
[XmlElement("cell5", Order = 5)]
public string Description { get; set; }
}
[Serializable, XmlRoot("rows")]
public class LocationsViewModel
{
[XmlElement("row")]
public List<LocationViewModel> Locations { get; set; }
}
This is what I want to get in the xml:
<rows>
<row id='1'>
<cell>1</cell>
<cell>Name sdfg</cell>
<cell/>
</row>
</rows>
If I set the XmlElement to "cell" for every property, I get an error.
The class LocationViewModel is used in a lot of places already and I would like to change it at least as possible in order to serialize it.

C# Deserializing a XML to an object List

I have this XML structure:
<?xml version="1.0" encoding="UTF-8" ?>
<response uri="/api/" action="EXPORT">
<result>
<rows>
<row>
<column name="Name1">Value1</column>
<column name="Name2">Value2</column>
</row>
<row>
<column name="Name1">Value1</column>
<column name="Name2">Value2</column>
</row>
</rows>
</result>
</response>
I'm trying to deserialize the XML into a list object like so:
List<ModelXML> model;
using (TextReader reader = new StringReader(xml_str))
{
System.Xml.Serialization.XmlSerializer deserializer = new System.Xml.Serialization.XmlSerializer(typeof(List<ModelXML>),
new XmlRootAttribute("rows"));
model= (List<ModelXML>)deserializer.Deserialize(reader);
}
My parameters in the ModelXML Class:
[XmlElement("Name1")]
public string Name1{ set; get; }
[XmlElement("Name2")]
public string Name2{ set; get; }
And finally I'm getting this error:
The '=' character, hexadecimal value 0x3D, cannot be included in a
name. Line 1, position 13.
What I'm doing wrong? thanks.
Here how you can solve your issue
First you have to change your model
[XmlRoot(ElementName = "column")]
public class Column
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlText]
public string Text { get; set; }
}
[XmlRoot(ElementName = "row")]
public class Row
{
[XmlElement(ElementName = "column")]
public List<Column> Column { get; set; }
}
[XmlRoot(ElementName = "rows")]
public class Rows
{
[XmlElement(ElementName = "row")]
public List<Row> Row { get; set; }
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "rows")]
public Rows Rows { get; set; }
}
[XmlRoot(ElementName = "response")]
public class Response
{
[XmlElement(ElementName = "result")]
public Result Result { get; set; }
[XmlAttribute(AttributeName = "uri")]
public string Uri { get; set; }
[XmlAttribute(AttributeName = "action")]
public string Action { get; set; }
}
Then
use the deserialization code like the following
//here I'm trying to load the file from the disk but you can do the same by passing a string
Response model;
var xml = File.ReadAllText("file.xml");
using (TextReader reader = new StringReader(xml))
{
System.Xml.Serialization.XmlSerializer deserializer = new System.Xml.Serialization.XmlSerializer(typeof(Response));
model = (Response)deserializer.Deserialize(reader);
}
More you can access your rows like this
var rows = model.Result.Rows;
//hope this can help
When I run your code I get the following exception.
System.InvalidOperationException: 'There is an error in XML document (2, 2).'
InnerException
InvalidOperationException: < response xmlns='' > was not expected.
This is because you must define the outer most element as the root element and not one deeper in the structure like your tried to do. One way to solve this is by defining all nessesary model classes like #BRAHIM Kamel did.
Ïf you don't want to have so many model classes and you don't care to much about performance you could also do this.
[XmlRoot("row")]
public class ModelXML
{
public class Column
{
[XmlAttribute("name")]
public string Name { set; get; }
[XmlText]
public string Value { set; get; }
}
[XmlElement("column")]
public List<Column> Columns { get; set; }
}
IEnumerable<T> Deserialize<T>(IEnumerable<XElement> elements)
{
foreach (var element in elements)
{
using (var reader = XDocument.Parse(element.ToString()).CreateReader())
{
XmlSerializer deserializer = new XmlSerializer(typeof(T));
yield return (T)deserializer.Deserialize(reader);
}
}
}
var document = XDocument.Parse(xml_str);
var collection = Deserialize<ModelXML>(
document.XPathSelectElements("response/result/rows/row"));

Xml deserialize array to list

I have following xml
<result>
<key accessMask="4294967295" type="Account" expires="">
<rowset name="characters" key="characterID" columns="characterID,characterName,corporationID,corporationName,allianceID,allianceName,factionID,factionName">
<row characterID="123" characterName="Sefa 123" corporationID="456" corporationName="Signal Cartel" allianceID="159" allianceName="Scouts" factionID="0" factionName=""/>
<row characterID="1234" characterName="Sefa 1234" corporationID="987" corporationName="Havos" allianceID="753" allianceName="Unlimited" factionID="0" factionName=""/>
</rowset>
</key>
</result>
And i have following Schema setup for deserializing this output.
[XmlRoot("result")]
public class ApiKeyInfo
{
[XmlElement("key")]
public Key Key { get; set; }
}
public class Key
{
[XmlAttribute("accessMask")]
public long AccessMask { get; set; }
[XmlAttribute("type")]
public string Type { get; set; }
[XmlElement("rowset")]
public List<AccountCharacter> Characters { get; set; }
}
public class AccountCharacter
{
[XmlAttribute("characterId")]
public long Id { get; set; }
[XmlAttribute("characterName")]
public string Name { get; set; }
[XmlAttribute("corporationID")]
public long CorpId { get; set; }
[XmlAttribute("corporationName")]
public string CorpName { get; set; }
[XmlAttribute("allianceID")]
public long AllianceId { get; set; }
[XmlAttribute("allianceName")]
public string AllianceName { get; set; }
[XmlAttribute("factionID")]
public long FactionId { get; set; }
[XmlAttribute("factionName")]
public string FactionName { get; set; }
}
Problem is, i can't deserialize character informations. Characters list is always containing 0 elements inside.
This:
[XmlElement("rowset")]
public List<AccountCharacter> Characters { get; set; }
Implies that you'll have a bunch of rowset elements, e.g:
<rowset characterID="123" characterName="Sefa 123" ...
Try this instead:
[XmlArray("rowset")]
[XmlArrayItem("row")]
public List<AccountCharacter> Characters { get; set; }
A useful tip for these sort of deserialisation problems is to try the process in reverse: create an object and serialise it and see what the XML looks like. It will likely give you some indication as to where your problem is.
See this fiddle for a working demo, it prints both row name values to the console.

XML Deserializing returns "some" null values

Here's my XML:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<p>this is an "event"</p>
</Description>
<Speakers>speaker1 LLC<br />speaker2<br />Jspeaker3</Speakers>
<Time>5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception</Time>
<Where></Where>
<RegistrationInfo>Please contact events#events.com to register for this event.</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content "can you display it."</content_teaser>
<content_text>text of the vent "more text" a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
<Event>.... Other events </Event>
<Events>
and here's are my classes:
public class Serializable_Events
{
[XmlElement("Event")]
public List<Serializable_Event> EventList = new List<Serializable_Event>();
}
public class Serializable_Event
{
[XmlElement("content_id")]
public string content_id { get; set; }
[XmlElement("content_title")]
public string content_title { get; set; }
[XmlElement("content_html")]
public Serializable_Event_ContentHTML ContentHTML { get; set; }
[XmlText]
public string content_teaser { get; set; }
[XmlElement("content_text")]
public string content_text { get; set; }
}
public class Serializable_Event_ContentHTML
{
[XmlElement("Date")]
public string Date { get; set; }
[XmlElement("EventType")]
public string EventType { get; set; }
[XmlElement("Description")]
public string Description { get; set; }
[XmlElement("Speakers")]
public string Speakers { get; set; }
[XmlElement("Time")]
public string Time { get; set; }
[XmlElement("Where")]
public string Where { get; set; }
[XmlElement("RegistrationInfo")]
public string RegistrationInfo { get; set; }
[XmlElement("Registration")]
public bool Registration { get; set; }
//ignored html tags
[XmlIgnore]
public string p { get; set; }
[XmlIgnore]
public string br { get; set; }
[XmlIgnore]
public string a { get; set; }
}
Implementation:
XmlSerializer ser = new XmlSerializer(typeof(Serializable_Events));
var data = (Serializable_Events)ser.Deserialize(new StreamReader(#"events.xml"));
My problem is that some attributes are null and some are not (see the screenshot)
The ones that are null, like <Description> are due to malformed
XML.
You are storing HMTL directly in XML with text all over the place, and the serializer is not expecting that; further you are telling the serializer to ignore HTML tags using XmlIgnore which is intended for XML tags with properly formed XML. That's a wrong use of XmlIgnore
All XML which contains non-XML mark-up should be wrapped in CDATA sections; this will solve your problem. Further, you can remove all of the XmlIgnore code as well since it's not needed.
Your XML should look like this:
<Events>
<Event>
<content_id>6442452774</content_id>
<content_title>Title of the event</content_title>
<content_html>
<Date>2015-11-18</Date>
<EventType>Events</EventType>
<Description>
<![CDATA[<p>this is an ""event""</p>]]>
</Description>
<Speakers>
<![CDATA[speaker1 LLC<br />speaker2<br />Jspeaker3]]>
</Speakers>
<Time>
<![CDATA[5:30 - 6:00pm Registration<br />6:00 - 7:00pm Panel Discussion<br />7:00 - 8:00pm Networking Reception]]>
</Time>
<Where></Where>
<RegistrationInfo>
<![CDATA[Please contact <a href='mailto:events#events.com'>events#events.com</a> to register for this event.]]>
</RegistrationInfo>
<Registration>false</Registration>
</content_html>
<date_created>2015-10-24T14:24:12.333</date_created>
<folder_id>262</folder_id>
<content_teaser>this is the content 'can you display it.'</content_teaser>
<content_text>text of the vent 'more text' a lot of text here </content_text>
<end_date>2015-11-19T21:35:00</end_date>
<content_type>1</content_type>
<template_id>43</template_id>
<content_status>A</content_status>
</Event>
</Events>"

Deserialize XML string not working

I have this XML string
<Root>
<Row>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</Row>
<Row>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</Row>
<Row>
<ITEMNO>2</ITEMNO>
<PARTSOURCE>MAKE</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>651321</CUSTPARTNO>
<DESCRIPT>Make Part</DESCRIPT>
</Row>
</Root>
I am trying to Deserialize it into this Root class
public class Root
{
public BOMItems Row { get; set; }
}
public class BOMItems
{
public string ITEMNO { get; set; }
public string USED { get; set; }
public string PARTSOURCE { get; set; }
public string QTY { get; set; }
public string CUSTPARTNO { get; set; }
public string CREV { get; set; }
public string DESCRIPT{ get; set; }
}
Using this method:
public Root TransformXMLToClass(string pXml)
{
var serializer = new XmlSerializer(typeof(Root));
XmlReader reader = XmlReader.Create(new StringReader(pXml));
return (Root)serializer.Deserialize(reader);
}
This works only on the first node.
I have tried changing the Root class like this:
public List<BOMItems> Row{get;set;}
It didn't work for any of the nodes
How do I get it to deserialize all nodes?
In your case it's quite simple. You just need to tell the serializer how to handle the collection of elements.
You do need to have the property as a collection or array like this:
public class Root
{
[XmlElement("Row")]
public BOMItems[] Row { get; set; }
}
The "[XmlElement]" is what will tell it how to deserialize correctly. Adding the XmlElementAttribute tells the serializer to treat it as a "flat" sequence.
<!-- Row Elements Flattened -->
<Root>
<Row>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</Row>
<Row>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</Row>
</Root>
<!-- Versus Row Elements Unflattened -->
<Root>
<Row>
<BOMItems>
<ITEMNO>1</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>2</QTY>
<CUSTPARTNO>469</CUSTPARTNO>
<DESCRIPT>35W 1/4W 5%</DESCRIPT>
</BOMItems>
<BOMItems>
<ITEMNO>3</ITEMNO>
<PARTSOURCE>Buy</PARTSOURCE>
<QTY>5</QTY>
<CUSTPARTNO>116</CUSTPARTNO>
<DESCRIPT>1.74K 1/8W 1% Film</DESCRIPT>
</BOMItems>
</Row>
</Root>
Your BOM class should be something like below,
[XmlElement("ITEMNO")]
public string ITEMNO { get; set; }
so as to inform the serializer that you read ITEMNO and save it in the ITEMNO
EDIT:
It has to be done for every property of BOM class.
Answer: (with the list )
public class Root
{
[XmlElement("Row")]
public List<BOMItems> Row { get; set; }
}
public class BOMItems
{
[XmlElement("ITEMNO")]
public string ITEMNO { get; set; }
[XmlElement("USED")]
public string USED { get; set; }
[XmlElement("PARTSOURCE")]
public string PARTSOURCE { get; set; }
[XmlElement("QTY")]
public string QTY { get; set; }
[XmlElement("CUSTPARTNO")]
public string CUSTPARTNO { get; set; }
[XmlElement("CREV")]
public string CREV { get; set; }
[XmlElement("DESCRIPT")]
public string DESCRIPT { get; set; }
}
class Program
{
static void Main(string[] args)
{
var serializer = new XmlSerializer(typeof(Root));
var reader = XmlReader.Create(new StringReader(File.ReadAllText("c:\\tet.xml")));
var serializedOutput = (Root)serializer.Deserialize(reader);
Console.ReadKey();
}

Categories