Reputation: 841
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.
Upvotes: 0
Views: 533
Reputation: 11367
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"));
Upvotes: 0
Reputation: 13765
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
Upvotes: 1