I am trying to solve a puzzle with xml attributes. The problem is that we already have widely used file with this structure, from which I can't deviate
<CONFIGS>
<CONFIG>
<NAME>c1</NAME>
<DB>
<VAL1>v1</VAL1>
<VAL2>v2</VAL2>
<VAL3>v3</VAL3>
</DB>
</CONFIG>
<CONFIG>
<NAME>c2</NAME>
<DB>
<VAL1>v1</VAL1>
<VAL2>v2</VAL2>
<VAL3>v3</VAL3>
</DB>
</CONFIG>
</CONFIGS>
I've created this c# code
// master class
[XmlRoot(ElementName = "CONFIGS")]
public class MyConfigs
{
[XmlArrayItem(ElementName = "CONFIG", Type = typeof(MyConfigSchema))]
public MyConfigSchema[] Schemas { get; set; }
}
// I should have array of these
public class MyConfigSchema
{
[XmlElement(DataType = "string", ElementName = "NAME")]
public string Name { get; set; }
[XmlElement(ElementName = "DB", Type = typeof(Db))]
public Db Config { get; set; }
// this element is single and has subelements
public class Db
{
[XmlElement(DataType = "string", ElementName = "VAL1")]
public string Val1 { get; set; }
[XmlElement(DataType = "int", ElementName = "VAL2")]
public int Val2 { get; set; }
[XmlElement(DataType = "string", ElementName = "VAL3")]
public string Val3 { get; set; }
}
}
// Writing
using (var writer = new FileStream(testfile, FileMode.Create))
{
var ser = new XmlSerializer(typeof(MyConfigs));
ser.Serialize(writer, confFileObj);
writer.Close();
}
Here is my issue - it writes the following output, which is almost what I need but in there it writes <Schemas>. . . </Schemas> that I can't have.
<CONFIGS>
--<Schemas>--
<CONFIG>
<NAME>c1</NAME>
<DB>
<VAL1>v1</VAL1>
<VAL2>v2</VAL2>
<VAL3>v3</VAL3>
</DB>
</CONFIG>
<CONFIG>
<NAME>c2</NAME>
<DB>
<VAL1>v1</VAL1>
<VAL2>v2</VAL2>
<VAL3>v3</VAL3>
</DB>
</CONFIG>
--</Schemas>--
</CONFIGS>
Is there a way of get rid of <Schemas>. . . </Schemas>?
Looks like I just solved it. I have never seen this before, looked on MSDN, hence I didn't try it. But I tried instead of this
[XmlArrayItem(ElementName = "CONFIG", Type = typeof(MyConfigSchema))]
public MyConfigSchema[] Schemas { get; set; }
do this
[XmlElement(ElementName = "CONFIG", Type = typeof(MyConfigSchema))]
public MyConfigSchema[] Schemas { get; set; }
Instead of XmlArrayItem I placed XmlElement and it worked. I didn't know one can mark List or array with plain element attribute.
Related
I am trying to cast an XML document to a C# class, and for the most part, it's working fine, but in my XML I have a custom prefix, which gives me some trouble. I don't have any control over how the XML file is being generated.
<mxb:bike>Test Bike</mxb:bike>
I'm getting stuck on the mxb part since it isn't declared. My problem is that it's not declared in the XML file itself, since otherwise, it wouldn't throw the error in the first place, but I hope there is a way of solving this code side. I'm working with a .NET application, and am trying to parse an XML file to a C# model.
I'm getting the data through a post request on an API endpoint, which when I specify a model automatically converts it to that model.
My XML input is as following:
<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" xmlns:gpxacx="http://www.garmin.com/xmlschemas/AccelerationExtension/v1">
<metadata>
<time>2022-09-25T12:06:47.081Z</time>
<extensions>
<mxb:bike>Test Bike</mxb:bike>
<mxb:notes>Testing</mxb:notes>
<mxb:conditions>Dry</mxb:conditions>
<mxb:track>Test Track</mxb:track>
</extensions>
</metadata>
<trk>
<trkseg>
<trkpt lat="52.914892" lon="4.776444">
<time>2022-09-25T12:06:47.081Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>
My C# model looks like this:
public class GpxData
{
[XmlRoot(ElementName="extensions", Namespace="http://www.topografix.com/GPX/1/1")]
public class Extensions {
[XmlElement(ElementName="bike", Namespace="")]
public string? Bike { get; set; }
[XmlElement(ElementName="notes", Namespace="")]
public string? Notes { get; set; }
[XmlElement(ElementName="conditions", Namespace="")]
public string? Conditions { get; set; }
[XmlElement(ElementName="track", Namespace="")]
public string? Track { get; set; }
}
[XmlRoot(ElementName="metadata", Namespace="http://www.topografix.com/GPX/1/1")]
public class Metadata {
[XmlElement(ElementName="time", Namespace="http://www.topografix.com/GPX/1/1")]
public DateTime Time { get; set; }
[XmlElement(ElementName="extensions", Namespace="http://www.topografix.com/GPX/1/1")]
public Extensions Extensions { get; set; }
}
[XmlRoot(ElementName = "trkpt", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trkpt
{
[XmlElement(ElementName = "time", Namespace = "http://www.topografix.com/GPX/1/1")]
public DateTime Time { get; set; }
[XmlAttribute(AttributeName = "lat", Namespace = "")]
public double Lat { get; set; }
[XmlAttribute(AttributeName = "lon", Namespace = "")]
public double Lon { get; set; }
}
[XmlRoot(ElementName = "trkseg", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trkseg
{
[XmlElement(ElementName = "trkpt", Namespace = "http://www.topografix.com/GPX/1/1")]
public List<Trkpt> Trkpt { get; set; }
}
[XmlRoot(ElementName = "trk", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Trk
{
[XmlElement(ElementName = "trkseg", Namespace = "http://www.topografix.com/GPX/1/1")]
public Trkseg Trkseg { get; set; }
}
[XmlRoot(ElementName = "gpx", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Gpx
{
[XmlElement(ElementName="metadata", Namespace="http://www.topografix.com/GPX/1/1")]
public Metadata Metadata { get; set; }
[XmlElement(ElementName = "trk", Namespace = "http://www.topografix.com/GPX/1/1")]
public Trk Trk { get; set; }
[XmlAttribute(AttributeName = "creator", Namespace = "")]
public string Creator { get; set; }
}
Whenever I remove the part within the "extensions" tag, it works completely fine.
When I only remove the mxb part, and just keep the part with for example "bike" it doesn't work either.
I tried to declare the MXB prefix in the XML file itself, but since I don't have any control over the XML generation, I can't really change anything within the file, since that would only be a temporary solution, besides the fact that I don't have a schema, and as far as I know, I can't declare a prefix, without giving it a schema. Even if that would work, that wouldn't be a good solution in my case. I also tried to remove the mxb part in the XML file, and even though that solved the undeclared error issue, it would just result in the information not being cast to the model.
All the solutions I tried were related to changing something in the XML file, but that's not something I can do ;-(
I'm pretty new to XML serialzation \ deseralation, so I hope someone is able to help me! Thanks in advance.
Inspired from this answer.
You can inject a custom XmlNamespaceManager to correct missing namespace.
public class MyXmlNamespaceManager : XmlNamespaceManager
{
const string MissingNamespacePrefix = "http://missing.namespace.prefix.net/2014/";
public MyXmlNamespaceManager(XmlNameTable nameTable)
: base(nameTable)
{ }
void AddMissingNamespace(string prefix)
{
if (string.IsNullOrEmpty(prefix))
return;
string uri = MissingNamespacePrefix + prefix;
AddNamespace(prefix, uri);
}
public override bool HasNamespace(string prefix)
{
var result = base.HasNamespace(prefix);
if (!result)
AddMissingNamespace(prefix);
result = base.HasNamespace(prefix);
return result;
}
public override string LookupNamespace(string prefix)
{
var result = base.LookupNamespace(prefix);
if (result == null)
AddMissingNamespace(prefix);
result = base.LookupNamespace(prefix);
return result;
}
}
Thereby, the extension node become :
<extensions>
<mxb:bike xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Test Bike</mxb:bike>
<mxb:notes xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Testing</mxb:notes>
<mxb:conditions xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">Dry</mxb:conditions>
<mxb:track xmlns:mxb="http://missing.namespace.prefix.net/2014/mxb">mxb Track</mxb:track>
</extensions>
You need to adapt your model class like :
[XmlRoot(ElementName = "extensions", Namespace = "http://www.topografix.com/GPX/1/1")]
public class Extensions
{
[XmlElement(ElementName = "bike", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Bike { get; set; }
[XmlElement(ElementName = "notes", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Notes { get; set; }
[XmlElement(ElementName = "conditions", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Conditions { get; set; }
[XmlElement(ElementName = "track", Namespace = "http://missing.namespace.prefix.net/2014/mxb")]
public string? Track { get; set; }
}
Then deserialize like :
var xml = "...";
// Fix the Xml
XmlDocument xmlDoc;
using (var stream = new StringReader(xml))
{
var settings = new XmlReaderSettings();
settings.NameTable = new NameTable();
var manager = new MyXmlNamespaceManager(settings.NameTable);
XmlParserContext context = new XmlParserContext(null, manager, null, XmlSpace.Default);
using (var xmlReader = XmlReader.Create(stream, settings, context))
{
xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
}
}
// Deserialize
using (var stream = new MemoryStream())
{
xmlDoc.Save(stream);
stream.Seek(0, SeekOrigin.Begin);
var serializer = new XmlSerializer(typeof(GpxData.Gpx));
var result = serializer.Deserialize(stream) as GpxData.Gpx;
Console.WriteLine(result.Metadata.Extensions.Bike);
}
I'm trying to deserialize an XML file to an object array, but I'm receiving empty objects.
My question looks similar to this: How to Deserialize xml to an array of objects? but I can't seem to create a class which inherits IXmlSerializable. That said, I don't think that approach is necessary.
Am I doing something wrong?
File Object
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Name { get; set; }
[XmlElement("docs")]
public HashSet<doc> Docs { get; set; }
}
Doc Object
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file>
<id>12345</id>
<company_name>Apple</company_name>
<docs>
<doc>
<valA>Info</valA>
<valB>More Info</valB>
</doc>
</docs>
</file>
<file>
<id>12345</id>
<company_name>Microsoft</company_name>
<docs>
<doc>
<valA>Even More Info</valA>
<valB>Lots of it</valB>
</doc>
</docs>
</file>
</files>
Deserialization code
XmlSerializer mySerializer = new XmlSerializer(typeof(File[]), new XmlRootAttribute("files"));
using (FileStream myFileStream = new FileStream("Files.xml", FileMode.Open))
{
File[] r;
r = (File[])mySerializer.Deserialize(myFileStream);
}
You have decorated your properties with XMLAttribute but they are elements in your XML. So, change all XMLAttribute to XmlElement.
[XmlType("file")]
public class File
{
[XmlElement("id")]
public string Id { get; set; }
[XmlElement("company_name")]
public string Company_Id { get; set; }
[XmlArray("docs")]
public HashSet<Doc> Docs { get; set; }
}
[XmlType("doc")]
public class Doc
{
[XmlElement("valA")]
public string ValA { get; set; }
[XmlElement("valB")]
public string ValB { get; set; }
}
Also you XML is not well formed. I guess this is typo though -
<company_name>Apple</company_id>
<company_name>Microsoft</company_id>
Ending tag should be company_name -
<company_name>Apple</company_name>
<company_name>Microsoft</company_name>
I would use xml parser..
XDocument doc=XDocument.Load(url);
File[] r=doc.Elements("file")
.Select(f=>
new File
{
Id=f.Element("id").Value,
Company_Id=f.Element("company_name").Value,
Docs=new HashSet<Docs>(
f.Elements("docs")
.Elements("doc")
.Select(d=>
new Doc
{
ValA=d.Element("valA").Value,
ValB=d.Element("valB").Value
}))
}).ToArray();
i need some help, i get allways null if i will deserialize a string between two xml tags.
The following example xml file:
<?xml version="1.0" encoding="utf-8" ?>
<item name='First Item' size='1'>
<Bits value='0'>
1st String
</Bits>
<Bits value='1'>
2nd String
</Bits>
</item>
And i write the following classes:
[Serializable()]
public class Bits
{
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
[XmlAttribute("value")]
public int entryValue { get; set; }
}
[Serializable()]
[XmlRoot("item")]
public class itemsReader
{
public itemsReader()
{
_bitList = new List<Bits>();
}
[XmlElement("Bits")]
public List<Bits> _bitList { get; set; }
[XmlAttribute("name")]
public String entryName { get; set; }
[XmlAttribute("size")]
public int entrySize { get; set; }
}
Only the entryString is always null!
To readout the XML file i use the following:
itemsReader ireader = null;
String path = #"PathtoString";
XmlSerializer serializer = new XmlSerializer(typeof(itemsReader));
var reader = File.OpenText(path);
ireader = (itemsReader)serializer.Deserialize(reader);
Thanks for help!
You have decorated entryString with XmlElement attribute which will search for an element Bits inside Bits itself.
But you want inner text of Bits element. For that we have another attribute called XmlText.
So change this
[XmlElement(ElementName = "Bits")]
public String entryString { get; set; }
to
[XmlText]
public String entryString { get; set; }
i ran your code on your input and got the output, but the i saw, in the Bits class, that the property entryString has an attribute
[XmlElement(ElementName = "Bits")]
but in your xml file there is no <Bits> tags around 1st String. so i added them and got:
<?xml version="1.0"?>
<item name="First Item" size="2">
<Bits value="1">
<Bits>firstOne</Bits>
</Bits>
<Bits value="2">
<Bits>secOne</Bits>
</Bits>
</item>
and then your code worked
so you can change the xml file or get rid of the attribute. your call
I'm pulling in the XML from Twitter via OAuth.
I'm doing a request to http://twitter.com/account/verify_credentials.xml, which returns the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<id>16434938</id>
<name>Lloyd Sparkes</name>
<screen_name>lloydsparkes</screen_name>
<location>Hockley, Essex, UK</location>
<description>Student</description>
<profile_image_url>http://a3.twimg.com/profile_images/351849613/twitterProfilePhoto_normal.jpg</profile_image_url>
<url>http://www.lloydsparkes.co.uk</url>
<protected>false</protected>
<followers_count>115</followers_count>
<profile_background_color>9fdaf4</profile_background_color>
<profile_text_color>000000</profile_text_color>
<profile_link_color>220f7b</profile_link_color>
<profile_sidebar_fill_color>FFF7CC</profile_sidebar_fill_color>
<profile_sidebar_border_color>F2E195</profile_sidebar_border_color>
<friends_count>87</friends_count>
<created_at>Wed Sep 24 14:26:09 +0000 2008</created_at>
<favourites_count>0</favourites_count>
<utc_offset>0</utc_offset>
<time_zone>London</time_zone>
<profile_background_image_url>http://s.twimg.com/a/1255366924/images/themes/theme12/bg.gif</profile_background_image_url>
<profile_background_tile>false</profile_background_tile>
<statuses_count>1965</statuses_count>
<notifications>false</notifications>
<geo_enabled>false</geo_enabled>
<verified>false</verified>
<following>false</following>
<status>
<created_at>Mon Oct 12 19:23:47 +0000 2009</created_at>
<id>4815268670</id>
<text>ยป #alexmuller your kidding? it should all be "black tie" dress code</text>
<source><a href="http://code.google.com/p/wittytwitter/" rel="nofollow">Witty</a></source>
<truncated>false</truncated>
<in_reply_to_status_id>4815131457</in_reply_to_status_id>
<in_reply_to_user_id>8645442</in_reply_to_user_id>
<favorited>false</favorited>
<in_reply_to_screen_name>alexmuller</in_reply_to_screen_name>
<geo/>
</status>
</user>
I am using the following code to deserialize:
public User VerifyCredentials()
{
string url = "http://twitter.com/account/verify_credentials.xml";
string xml = _oauth.oAuthWebRequestAsString(oAuthTwitter.Method.GET, url, null);
XmlSerializer xs = new XmlSerializer(typeof(User),"");
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xml));
return (User)xs.Deserialize(ms);
}
And I have the following for my User class:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class User
{
[XmlElement(ElementName = "id")]
public long Id { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "screen_name")]
public string ScreenName { get; set; }
[XmlElement(ElementName = "location")]
public string Location { get; set; }
[XmlElement(ElementName = "description")]
public string Description { get; set; }
[XmlElement(ElementName = "profile_image_url")]
public string ProfileImageUrl { get; set; }
[XmlElement(ElementName = "url")]
public string Url { get; set; }
[XmlElement(ElementName = "protected")]
public bool Protected { get; set; }
[XmlElement(ElementName = "followers_count")]
public int FollowerCount { get; set; }
[XmlElement(ElementName = "profile_background_color")]
public string ProfileBackgroundColor { get; set; }
[XmlElement(ElementName = "profile_text_color")]
public string ProfileTextColor { get; set; }
[XmlElement(ElementName = "profile_link_color")]
public string ProfileLinkColor { get; set; }
[XmlElement(ElementName = "profile_sidebar_fill_color")]
public string ProfileSidebarFillColor { get; set; }
[XmlElement(ElementName = "profile_sidebar_border_color")]
public string ProfileSidebarBorderColor { get; set; }
[XmlElement(ElementName = "friends_count")]
public int FriendsCount { get; set; }
[XmlElement(ElementName = "created_at")]
public string CreatedAt { get; set; }
[XmlElement(ElementName = "favourties_count")]
public int FavouritesCount { get; set; }
[XmlElement(ElementName = "utc_offset")]
public int UtcOffset { get; set; }
[XmlElement(ElementName = "time_zone")]
public string Timezone { get; set; }
[XmlElement(ElementName = "profile_background_image_url")]
public string ProfileBackgroundImageUrl { get; set; }
[XmlElement(ElementName = "profile_background_tile")]
public bool ProfileBackgroundTile { get; set; }
[XmlElement(ElementName = "statuese_count")]
public int StatusesCount { get; set; }
[XmlElement(ElementName = "notifications")]
public string Notifications { get; set; }
[XmlElement(ElementName = "geo_enabled")]
public bool GeoEnabled { get; set; }
[XmlElement(ElementName = "Verified")]
public bool Verified { get; set; }
[XmlElement(ElementName = "following")]
public string Following { get; set; }
[XmlElement(ElementName = "status", IsNullable=true)]
public Status CurrentStatus { get; set; }
}
But when it's deserializing the above XML the application throws the following:
$exception {"There is an error in XML document (2, 2)."} System.Exception {System.InvalidOperationException}
InnerException {"<user xmlns=''> was not expected."} System.Exception {System.InvalidOperationException}
Now I have searched around and the best solution I can find is to add blank namespaces to the serializer when you serialize the content, but i'm not serializing it so I can't.
I also have some code for receiving Statuses, which works fine.
So can someone explain to me why the error is happening? As well as a possible solution?
Either decorate your root entity with the XmlRoot attribute which will be used at compile time.
[XmlRoot(Namespace = "www.contoso.com", ElementName = "MyGroupName", DataType = "string", IsNullable=true)]
Or specify the root attribute when de serializing at runtime.
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "user";
// xRoot.Namespace = "http://www.cpandl.com";
xRoot.IsNullable = true;
XmlSerializer xs = new XmlSerializer(typeof(User),xRoot);
Even easier is just to add the following annotations to the top of your class:
[Serializable, XmlRoot("user")]
public partial class User
{
}
XmlSerializer xs = new XmlSerializer(typeof(User), new XmlRootAttribute("yourRootName"));
The error message is so vague, for me I had this code:
var streamReader = new StreamReader(response.GetResponseStream());
var xmlSerializer = new XmlSerializer(typeof(aResponse));
theResponse = (bResponse) xmlSerializer.Deserialize(streamReader);
Notice xmlSerializer is instantiated with aResponse but on deserializing I accidentally casted it to bResonse.
The simplest and best solution is just to use XMLRoot attribute in your class, in which you wish to deserialize.
Like:
[XmlRoot(ElementName = "YourPreferableNameHere")]
public class MyClass{
...
}
Also, use the following Assembly :
using System.Xml.Serialization;
In my case, my xml had multiple namespaces and attributes.
So I used this site to generate the objects - https://xmltocsharp.azurewebsites.net/
And used the below code to deserialize
XmlDocument doc = new XmlDocument();
doc.Load("PathTo.xml");
User obj;
using (TextReader textReader = new StringReader(doc.OuterXml))
{
using (XmlTextReader reader = new XmlTextReader(textReader))
{
XmlSerializer serializer = new XmlSerializer(typeof(User));
obj = (User)serializer.Deserialize(reader);
}
}
As John Saunders says, check if the class/property names matches the capital casing of your XML. If this isn't the case, the problem will also occur.
The only thing that worked in my case was by using david valentine code. Using Root Attr. in the Person class did not help.
I have this simple Xml:
<?xml version="1.0"?>
<personList>
<Person>
<FirstName>AAAA</FirstName>
<LastName>BBB</LastName>
</Person>
<Person>
<FirstName>CCC</FirstName>
<LastName>DDD</LastName>
</Person>
</personList>
C# class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
De-Serialization C# code from a Main method:
XmlRootAttribute xRoot = new XmlRootAttribute();
xRoot.ElementName = "personList";
xRoot.IsNullable = true;
using (StreamReader reader = new StreamReader(xmlFilePath))
{
List<Person> result = (List<Person>)(new XmlSerializer(typeof(List<Person>), xRoot)).Deserialize(reader);
int numOfPersons = result.Count;
}
My issue was that the root element actually has a xmlns="abc123"
So had to make XmlRoot("elementname",NameSpace="abc123")
Nothing worked for me for these errors EXCEPT
... was not expected,
... there is an error in XML document (1,2)
... System.FormatException Input String was not in correct format ...
Except this way
1- You need to inspect the xml response as string (the response that you are trying to de-serialize to an object)
2- Use online tools for string unescape and xml prettify/formatter
3- MAKE SURE that the C# Class (main class) you are trying to map/deserialize the xml string to HAS AN XmlRootAttribute that matches the root element of the response.
Exmaple:
My XML Response was staring like :
<ShipmentCreationResponse xmlns="http://ws.aramex.net/ShippingAPI/v1/">
<Transaction i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
....
And the C# class definition + attributes was like :
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="ShipmentCreationResponse", WrapperNamespace="http://ws.aramex.net/ShippingAPI/v1/", IsWrapped=true)]
public partial class ShipmentCreationResponse {
.........
}
Note that the class definition does not have "XmlRootAttribute"
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
And when i try to de serialize using a generic method :
public static T Deserialize<T>(string input) where T : class
{
System.Xml.Serialization.XmlSerializer ser = new System.Xml.Serialization.XmlSerializer(typeof(T));
using (System.IO.StringReader sr = new System.IO.StringReader(input))
{
return (T)ser.Deserialize(sr);
}
}
var _Response = GeneralHelper.XMLSerializer.Deserialize<ASRv2.ShipmentCreationResponse>(xml);
I was getting the errors above
... was not expected, ... there is an error in XML document (1,2) ...
Now by just adding the "XmlRootAttribute" that fixed the issue for ever and for every other requests/responses i had a similar issue with:
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
..
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://ws.aramex.net/ShippingAPI/v1/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://ws.aramex.net/ShippingAPI/v1/", IsNullable = false)]
public partial class ShipmentCreationResponse
{
........
}
My problem was one of my elements had the xmlns attribute:
<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
<RETS-RESPONSE xmlns="blahblah">
...
</RETS-RESPONSE>
</RETS>
No matter what I tried the xmlns attribute seemed to be breaking the serializer, so I removed any trace of xmlns="..." from the xml file:
<?xml version="1.0" encoding="utf-8"?>
<RETS ReplyCode="0">
<RETS-RESPONSE>
...
</RETS-RESPONSE>
</RETS>
and voila! Everything worked.
I now parse the xml file to remove this attribute before deserializing.
Not sure why this works, maybe my case is different since the element containing the xmlns attribute is not the root element.
All above not worked for me, but this was:
Check that the name of Root element of class is exactly like the one from XML case sensitive.
This is my first time using XML Serialization and this is driving me absolutely nuts after 2 days of trying to troubleshoot this.
I get this error when the deserialization kicks in:
The XML element 'name' from namespace '' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element.
The error happens on this line in my code:
Album album = (Album)serializer.Deserialize(reader);
I not sure why. There is no dup "name" node so I just don't get it. This is an XML doc received from an HttpWebResponse from a 3rd party REST API.
Here's the complete code:
My Album Class (the type I'm Deserializing to):
public class Album
{
#region Constructors
public Album()
{
}
#endregion
#region ElementConstants
public static class ElementConstants
{
public const string aID = "aid";
public const string Owner = "owner";
public const string AlbumName = "name";
public const string CoverPhotoID = "cover_pid";
public const string CreateDate = "created";
public const string LastModifiedDate = "modified";
public const string Description = "description";
public const string Location = "location";
public const string AlbumURL = "link";
public const string Size = "size";
public const string Visible = "visible";
}
#endregion ElementConstants
#region Public Properties
[XmlArray(ElementName = "photos_GetAlbums_response")]
[XmlArrayItem( "album" )]
public Album[] Albums { get; set; }
[XmlElement (ElementName = ElementConstants.AlbumName, DataType = "string")]
public string AlbumID { get; set; }
[XmlElement(ElementName = ElementConstants.aID, DataType = "int")]
public Int32 CoverPhotoID { get; set; }
[XmlElement(ElementName = ElementConstants.Owner, DataType = "string")]
public string Owner { get; set; }
[XmlElement(ElementName = ElementConstants.AlbumName, DataType = "string")]
public string AlbumName { get; set; }
[XmlElement(ElementName = ElementConstants.aID, DataType = "DateTime")]
public DateTime CreateDate { get; set; }
[XmlElement(ElementName = ElementConstants.LastModifiedDate, DataType = "DateTime")]
public DateTime LastModifiedDate { get; set; }
[XmlElement(ElementName = ElementConstants.Description, DataType = "string")]
public string Description { get; set; }
[XmlElement(ElementName = ElementConstants.Location, DataType = "string")]
public string Location { get; set; }
[XmlElement(ElementName = ElementConstants.AlbumURL, DataType = "string")]
public string Link { get; set; }
[XmlElement(ElementName = ElementConstants.Size, DataType = "size")]
public string Size { get; set; }
[XmlElement(ElementName = ElementConstants.Visible, DataType = "string")]
public string Visible { get; set; }
#endregion
}
My Serializer Class:
public class Serializer
{
public static Album CreateAlbumFromXMLDoc(XmlDocument doc)
{
// Create an instance of a serializer
var serializer = new XmlSerializer(typeof(Album));
var reader = new StringReader(doc.ToString());
// Deserialize the Xml Object and cast to type Album
Album album = (Album)serializer.Deserialize(reader);
return album;
}
}
The XML that I am trying to Deserialized (copied from the Xml Doc object being passed into the CreateAlbumFromXMLDoc method when debugging in VS):
<?xml version="1.0" encoding="UTF-8"?>
<photos_GetAlbums_response xsi:schemaLocation="http://api.example.com/1.0/ http://api.example.com/1.0/xxx.xsd" list="true">
<album>
<aid>3231990241086938677</aid>
<cover_pid>7031990241087042549</cover_pid>
<owner>1337262814</owner>
<name>LA</name>
<created>1233469624</created>
<modified>1233469942</modified>
<description>trip to LA</description>
<location>CA</location>
<link>http://www.example.com/album.php?aid=7333&id=1337262814</link>
<size>48</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086936240</aid>
<cover_pid>7031990241087005994</cover_pid>
<owner>1337262814</owner>
<name>Wall Photos</name>
<created>1230437805</created>
<modified>1233460690</modified>
<description/>
<location/>
<link>http://www.example.com/album.php?aid=3296&id=1337262814</link>
<size>34</size>
<visible>everyone</visible>
</album>
<album>
<aid>7031990241086937544</aid>
<cover_pid>7031990241087026027</cover_pid>
<owner>1337262814</owner>
<name>Mobile Uploads</name>
<created>1231984989</created>
<modified>1233460349</modified>
<description/>
<location/>
<link>http://www.example.com/album.php?aid=6300&id=1337262814</link>
<size>3</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086936188</aid>
<cover_pid>7031990241087005114</cover_pid>
<owner>1337262814</owner>
<name>Christmas 2008</name>
<created>1230361978</created>
<modified>1230362306</modified>
<description>My Album</description>
<location/>
<link>http://www.example.com/album.php?aid=5234&id=1337262814</link>
<size>50</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086935881</aid>
<cover_pid>7031990241087001093</cover_pid>
<owner>1637262814</owner>
<name>Hock</name>
<created>1229889219</created>
<modified>1229889235</modified>
<description>Misc Pics</description>
<location/>
<link>http://www.example.com/album.php?aid=4937&id=1637262814</link>
<size>1</size>
<visible>friends-of-friends</visible>
</album>
<album>
<aid>7031990241086935541</aid>
<cover_pid>7031990241086996817</cover_pid>
<owner>1637262814</owner>
<name>Test Album 2 (for work)</name>
<created>1229460455</created>
<modified>1229460475</modified>
<description>this is a test album</description>
<location/>
<link>http://www.example.com/album.php?aid=4547&id=1637262814</link>
<size>1</size>
<visible>everyone</visible>
</album>
<album>
<aid>7031990241086935537</aid>
<cover_pid>7031990241086996795</cover_pid>
<owner>1637262814</owner>
<name>Test Album (for work)</name>
<created>1229459168</created>
<modified>1229459185</modified>
<description>Testing for work</description>
<location/>
<link>http://www.example.com/album.php?aid=4493&id=1637262814</link>
<size>1</size>
<visible>friends</visible>
</album>
</photos_GetAlbums_response>
A side note: Just for the hell of it, I paste that XML into XML Notepad 2007, it tells me:
Your XML document contains no xml-stylesheet processing instruction. To provide an XSLT transform, add the following to the top of your file and edit the href attribute accordingly:
I don't think that really means it's malformed or anything but just something to note.
So..
My ultimate goal is to get pass this damn error obviously and get an array of albums back using my code above once I can get past the error. I also want to make sure my code is correct in trying to retrieve that arrray back of albums using my Album[] property in my Album class or anything else I might be missing here. I think it's pretty close and should work but it's not.
Follow-up. I've been pulling my hair out since then.
Here's the latest. I did not use some things for now (from Marc) like the Enum, etc. I might change that later. I also pulled out the datetime stuff as it just looked wierd and I did not get errors on that anway without...at least yet. The main problem now is still my damn XML.
It's still appearing to have problems with the format I guess? Unless it's covering up another problem, no clue. This is driving me fing crazy.
I now get this error when the deserialization kicks in:
Data at the root level is invalid. Line 1, position 1.
The error happens on this line in my code: GetAlbumsResponse album = (GetAlbumsResponse)serializer.Deserialize(reader);
How I get the response into an XmL doc:
public static XmlDocument GetResponseXmlDocument(HttpWebResponse response)
{
Stream dataStream = null; // stream from WebResponse
XmlDocument doc = new XmlDocument();
if (doc == null)
{
throw new NullReferenceException("The web reponse was null");
}
// Get the response stream so we can read the body of the response
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access
StreamReader reader = new StreamReader(dataStream);
// Load response into string variable so that we can then load into an XML doc
string responseString = reader.ReadToEnd();
// Create an XML document & load it with the response data
doc.LoadXml(responseString);
// Final XML document that represents the response
return doc;
}
My Album Class & Root Level Class (thanks to help from Marc..I get it now):
namespace xxx.Entities
{
[Serializable, XmlRoot("photos_GetAlbums_response")]
public class GetAlbumsResponse
{
[XmlElement("album")]
public List<Album> Albums { get; set; }
[XmlAttribute("list")]
public bool IsList { get; set; }
}
public class Album
{
#region Constructors
public Album()
{
}
#endregion
#region ElementConstants
/// <summary>
/// Constants Class to eliminate use of Magic Strings (hard coded strings)
/// </summary>
public static class ElementConstants
{
public const string aID = "aid";
public const string Owner = "owner";
public const string AlbumName = "name";
public const string CoverPhotoID = "cover_pid";
public const string CreateDate = "created";
public const string LastModifiedDate = "modified";
public const string Description = "description";
public const string Location = "location";
public const string AlbumURL = "link";
public const string Size = "size";
public const string Visible = "visible";
}
#endregion ElementConstants
#region Public Properties
[XmlElement (ElementName = ElementConstants.aID, DataType = "string")]
public string AlbumID { get; set; }
[XmlElement(ElementName = ElementConstants.CoverPhotoID, DataType = "int")]
public Int32 CoverPhotoID { get; set; }
[XmlElement(ElementName = ElementConstants.Owner, DataType = "string")]
public string Owner { get; set; }
[XmlElement(ElementName = ElementConstants.AlbumName, DataType = "string")]
public string AlbumName { get; set; }
public string Created { get; set; }
public DateTime Modified { get; set; }
[XmlElement(ElementName = ElementConstants.Description, DataType = "string")]
public string Description { get; set; }
[XmlElement(ElementName = ElementConstants.Location, DataType = "string")]
public string Location { get; set; }
[XmlElement(ElementName = ElementConstants.AlbumURL, DataType = "string")]
public string Link { get; set; }
public string Size { get; set; }
[XmlElement(ElementName = ElementConstants.Visible, DataType = "string")]
public string Visible { get; set; }
#endregion
}
}
My Serializer Class:
namespace xxx.Utilities
{
public class Serializer
{
public static List<Album> CreateAlbumFromXMLDoc(XmlDocument doc)
{
// Create an instance of a serializer
var serializer = new XmlSerializer(typeof(Album));
var reader = new StringReader(doc.ToString());
// Deserialize the Xml Object and cast to type Album
GetAlbumsResponse album = (GetAlbumsResponse)serializer.Deserialize(reader);
return album.Albums;
}
}
}
The true XML incoming, that I am trying to Deserialize (yes it does have xmlns):
<?xml version="1.0" encoding="UTF-8"?>
<photos_GetAlbums_response xmlns="http://api.example.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.example.com/1.0/ http://api.example.com/1.0/xxx.xsd" list="true">
<album>
<aid>7321990241086938677</aid>
<cover_pid>7031990241087042549</cover_pid>
<owner>1124262814</owner>
<name>Album Test 1</name>
<created>1233469624</created>
<modified>1233469942</modified>
<description>Our trip</description>
<location>CA</location>
<link>http://www.example.com/album.php?aid=7733&id=1124262814</link>
<size>48</size>
<visible>friends</visible>
</album>
<album>
<aid>231990241086936240</aid>
<cover_pid>7042330241087005994</cover_pid>
<owner>1124262814</owner>
<name>Album Test 2</name>
<created>1230437805</created>
<modified>1233460690</modified>
<description />
<location />
<link>http://www.example.com/album.php?aid=5296&id=1124262814</link>
<size>34</size>
<visible>everyone</visible>
</album>
<album>
<aid>70319423341086937544</aid>
<cover_pid>7032390241087026027</cover_pid>
<owner>1124262814</owner>
<name>Album Test 3</name>
<created>1231984989</created>
<modified>1233460349</modified>
<description />
<location />
<link>http://www.example.com/album.php?aid=6600&id=1124262814</link>
<size>3</size>
<visible>friends</visible>
</album>
</photos_GetAlbums_response>
Personally, I wouldn't use constants here - they make it hard to spot errors (and since you probably aren't re-using them, don't add much). For example:
[XmlElement (ElementName = ElementConstants.AlbumName, DataType = "string")]
public string AlbumID { get; set; }
...
[XmlElement(ElementName = ElementConstants.AlbumName, DataType = "string")]
public string AlbumName { get; set; }
Looks suspect to me...
An easier approach is to write the xml you want to a file (foo.xml, say) and use:
xsd foo.xml
xsd foo.xsd /classes
Then look at foo.cs.
Here we go... note the xml was invalid (& should be &; use of undeclared xsi namespace-alias). Note also that I added an enum for the visibility, added handling for converting the long to DateTime, and added the wrapper type:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
static class Program
{
const string xml = #"<?xml version=""1.0"" encoding=""UTF-8""?>
<photos_GetAlbums_response
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xsi:schemaLocation=""http://api.example.com/1.0/ http://api.example.com/1.0/xxx.xsd""
list=""true"">
<album>
<aid>3231990241086938677</aid>
<cover_pid>7031990241087042549</cover_pid>
<owner>1337262814</owner>
<name>LA</name>
<created>1233469624</created>
<modified>1233469942</modified>
<description>trip to LA</description>
<location>CA</location>
<link>http://www.example.com/album.php?aid=7333&id=1337262814</link>
<size>48</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086936240</aid>
<cover_pid>7031990241087005994</cover_pid>
<owner>1337262814</owner>
<name>Wall Photos</name>
<created>1230437805</created>
<modified>1233460690</modified>
<description/>
<location/>
<link>http://www.example.com/album.php?aid=3296&id=1337262814</link>
<size>34</size>
<visible>everyone</visible>
</album>
<album>
<aid>7031990241086937544</aid>
<cover_pid>7031990241087026027</cover_pid>
<owner>1337262814</owner>
<name>Mobile Uploads</name>
<created>1231984989</created>
<modified>1233460349</modified>
<description/>
<location/>
<link>http://www.example.com/album.php?aid=6300&id=1337262814</link>
<size>3</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086936188</aid>
<cover_pid>7031990241087005114</cover_pid>
<owner>1337262814</owner>
<name>Christmas 2008</name>
<created>1230361978</created>
<modified>1230362306</modified>
<description>My Album</description>
<location/>
<link>http://www.example.com/album.php?aid=5234&id=1337262814</link>
<size>50</size>
<visible>friends</visible>
</album>
<album>
<aid>7031990241086935881</aid>
<cover_pid>7031990241087001093</cover_pid>
<owner>1637262814</owner>
<name>Hock</name>
<created>1229889219</created>
<modified>1229889235</modified>
<description>Misc Pics</description>
<location/>
<link>http://www.example.com/album.php?aid=4937&id=1637262814</link>
<size>1</size>
<visible>friends-of-friends</visible>
</album>
<album>
<aid>7031990241086935541</aid>
<cover_pid>7031990241086996817</cover_pid>
<owner>1637262814</owner>
<name>Test Album 2 (for work)</name>
<created>1229460455</created>
<modified>1229460475</modified>
<description>this is a test album</description>
<location/>
<link>http://www.example.com/album.php?aid=4547&id=1637262814</link>
<size>1</size>
<visible>everyone</visible>
</album>
<album>
<aid>7031990241086935537</aid>
<cover_pid>7031990241086996795</cover_pid>
<owner>1637262814</owner>
<name>Test Album (for work)</name>
<created>1229459168</created>
<modified>1229459185</modified>
<description>Testing for work</description>
<location/>
<link>http://www.example.com/album.php?aid=4493&id=1637262814</link>
<size>1</size>
<visible>friends</visible>
</album>
</photos_GetAlbums_response>";
static void Main()
{
XmlSerializer ser = new XmlSerializer(typeof(GetAlbumsResponse));
GetAlbumsResponse response;
using (StringReader reader = new StringReader(xml))
{
response = (GetAlbumsResponse)ser.Deserialize(reader);
}
}
}
[Serializable, XmlRoot("photos_GetAlbums_response")]
public class GetAlbumsResponse
{
[XmlElement("album")]
public List<Album> Albums {get;set;}
[XmlAttribute("list")]
public bool IsList { get; set; }
}
public enum AlbumVisibility
{
[XmlEnum("")]
None,
[XmlEnum("friends")]
Friends,
[XmlEnum("friends-of-friends")]
FriendsOfFriends,
[XmlEnum("everyone")]
Everyone
}
[Serializable]
public class Album
{
static readonly DateTime epoch = new DateTime(1970, 1, 1);
static long SerializeDateTime(DateTime value)
{
return (long)((value - epoch).TotalSeconds);
}
static DateTime DeserializeDateTime(long value)
{
return epoch.AddSeconds(value);
}
[XmlElement("aid")]
public long AlbumID { get; set; }
[XmlElement("cover_pid")]
public long CoverPhotoID { get; set; }
[XmlElement("owner")]
public long Owner { get; set; }
[XmlElement("name")]
public string AlbumName { get; set; }
[XmlIgnore]
public DateTime CreateDate { get; set; }
[XmlElement("created"), Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public long CreateDateInt64 {
get {return SerializeDateTime(CreateDate);}
set {CreateDate = DeserializeDateTime(value);}
}
[XmlIgnore]
public DateTime LastModifiedDate { get; set; }
[XmlElement("modified"), Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public long LastModifiedDateInt64
{
get { return SerializeDateTime(LastModifiedDate); }
set { LastModifiedDate = DeserializeDateTime(value); }
}
[XmlElement("description")]
public string Description { get; set; }
[XmlElement("location")]
public string Location { get; set; }
[XmlElement("link")]
public string Link { get; set; }
[XmlElement("size")]
public int Size { get; set; }
[XmlElement("visible")]
public AlbumVisibility Visibility { get; set; }
}
(08 Feb) First, treating xml as a string (for reading) isn't going to cause errors.
The problem is the namespace (the xmlns without the xsi); this wasn't in the earlier xml, so I couldn't include it... basically, you need to tell the serializer about it:
[Serializable, XmlRoot("photos_GetAlbums_response",
Namespace="http://api.example.com/1.0/")]
public class GetAlbumsResponse { /* code as before */ }
[Serializable, XmlType(Namespace="http://api.example.com/1.0/")]
public class Album { /* code as before */ }
On this occasion, a constant for the namespace would make sense (since you are re-using it).
If the xml you are showing is accurate, then the links are still corrupt, though... but maybe this is just copy/paste (i.e. don't apply this change until you know it errors...): you need & (not &). Suggest some "Replace"... at the crudest level:
string fixedXml = xml.Replace("&", "&");
(although something more precise might be better - perhaps a regex)
Note that with the different data I also had to make some of the data strings (rather than long):
[XmlElement("aid")]
public string AlbumID { get; set; }
[XmlElement("cover_pid")]
public string CoverPhotoID { get; set; }
[XmlElement("owner")]
public string Owner { get; set; }
With these changes (and mostly my original code) it works.
Of course, by this point you should be thinking "I wish I'd used xsd".
Yes - album is definitely not the root node in your XML.
What I would recommend you do is create a GetAlbumsResponse class which contains a list of albums, and move your deserialize code to the wrapper class.
Basically, remove the root element from your Album class definition, and :
[XmlRoot (ElementName="GetAlbums_response")]
public class GetAlbumsResponse
{
#region Constructors
public GetAlbumsResponse()
{
}
#endregion
[XmlArray(ElementName="album")]
public List<Album> Albums{get;set;}
... deserialization code...
}
Well,
there is a link from Microsoft targeting your problem
The Xml that would work for your current code is something like this:
<Album><photos_GetAlbums_response>
<Album>
<photos_GetAlbums_response>
<Album>
<photos_GetAlbums_response> ....
A response, which has an array of Albums, where each Album has a response which is an Array of Albums...etc.
Anyway, I already helped you in your other question, and even went to the trouble of creating a full working code sample. Why did you create another question for the same problem ?
Use System.Xml.XmlDocument to parse the input. It shouldn't take more than an hour to write the code to extract the data yourself.
Ok - I coded up an example. I took a look at the Facebook API, now here is a FULL working example.
Try this:
[XmlRoot("photos_getAlbums_response", Namespace="http://api.facebook.com/1.0/")]
public class GetAlbumsResponse
{
public GetAlbumsResponse()
{
}
[XmlElement("album")]
public List<Album> Albums { get; set; }
}
public class Album
{
[XmlElement("aid")]
public long Aid{get;set;}
[XmlElement("cover_pid")]
public long CoverPid{get;set;}
[XmlElement("owner")]
public long Owner{get;set;}
[XmlElement("name")]
public string Name{get;set;}
[XmlElement("created")]
public long Created{get;set;}
[XmlElement("modified")]
public long Modified{get;set;}
[XmlElement("description")]
public string Description{get;set;}
[XmlElement("location")]
public string Location{get;set;}
[XmlElement("link")]
public string Link{get;set;}
[XmlElement("size")]
public int Size{get;set;}
[XmlElement("visible")]
public string Visible{get;set;}
public Album()
{}
}
class XmlUtils
{
public static T DeserializeFromXml<T>(string xml)
{
T result;
XmlSerializer ser = new XmlSerializer(typeof(T));
using (TextReader tr = new StringReader(xml))
{
result = (T)ser.Deserialize(tr);
}
return result;
}
}
Now.. with an xml photos_getAlbums_response from the Facebook API,
You can deserialize like this:
GetAlbumsResponse response = XmlUtils.DeserializeFromXml<GetAlbumsResponse>(xmlResponseString);
This is a really old thread but I just faced the same issue my self while tried to serialize two different list types in the same class under the same XmlArray name, something like
<Root>
<ArrayNode>
<SubnodeType1>...</SubnodeType1>
<SubnodeType1>...</SubnodeType1>
</ArrayNode>
</Root>
Or
<Root>
<ArrayNode>
<SubnodeType2>...</SubnodeType2>
<SubnodeType2>...</SubnodeType2>
</ArrayNode>
</Root>
What has worked for me was to use a class decoration like:
[XmlRoot(Namespace = "", ElementName = "Root")]
public class Root
{
[XmlArray(ElementName = "ArrayNode", Namespace = "", IsNullable = false, Order = 1)]
[XmlArrayItem("SubnodeType1")]
public List<SubnodeType1> SubnodeType1 { get; set; }
[XmlArray(ElementName = "ArrayNode", Namespace = "", IsNullable = false, Order = 2)]
[XmlArrayItem("SubnodeType2")]
public List<SubnodeType2> SubnodeType2 { get; set; }
}
Hope it help someone else :)