简体   繁体   中英

Problem deserializing generic List's with C# XmlSerializer

I've come up against a bit of a brick wall with Microsoft's .net XmlSerializer. I'm trying to deserialize some XML into an object, which is fine if I'm using a single object, but the problem comes when one puts an object into a List and tries to serialize/deserialize that. First up, here's a sample C# windows console program to illustrate the problem:

http://pastebin.com/m22e6e275

If the class 'Foo' is serialized as a root element, things behave fine, and as expected - the JezNamespace xmlns is applied to the root Foo element, and deserialization occurs fine. However if I create a List and serialize that, the XmlSerializer: - Creates a root element of ArrayOfFoo - Puts the Foo elements as children of that element - Sets the xmlns of EVERY child of Foo to the JezNamespace namespace!

I'm OK with the first two, but the third one seems mad... maybe a bug in XmlSerializer? Is there some way I can deal with this behaviour? I don't want to be specifying my namespace for every child of Foo, I just want to specify it for Foo. If I do that, currently, XmlSerializer doesn't deserialize the class properly - it just skips over any Foo element with the JezNamespace xmlns set. I have to set ALL the child elements to have that xmlns.

What I'd like to get to is XmlSerializer generating something like:

<ArrayOfFoo>
    <Foo xmlns="http://schemas.datacontract.org/2004/07/JezNamespace">
        <Field1>hello</Field1>
        <Field2>world</Field2>
    </Foo>
    <Foo xmlns="http://schemas.datacontract.org/2004/07/JezNamespace">
        <Field1>aaa</Field1>
        <Field2>bbb</Field2>
    </Foo>
</ArrayOfFoo>

... and then have XmlSerializer be able to deserialize that properly into a List. Any ideas how I can get it doing this?

Your code has two attributes on Foo that, so far as I can tell, you've put there to try to associate a namespace:

 [XmlRootAttribute(Namespace="http://schemas.datacontract.org/2004/07/JezNamespace",
                   IsNullable=false)]
 [XmlTypeAttribute(AnonymousType=true,
                   Namespace="http://schemas.datacontract.org/2004/07/JezNamespace")]

The first one is simply ignored, because in your scenario Foo is not a root element. The second one doesn't quite do what you probably think it does - the namespace in it is a namespace of an XSD type , not namespace of an element itself.

To specify name and namespace of the element, you do instead need to use XmlArrayItemAttribute on the List<Foo> property of a parent class (oh, and you will need that parent class):

public class FooParent
{
    [XmlArrayItem(ElementName="Foo",
                  Namespace="http://schemas.datacontract.org/2004/07/JezNamespace")]
    public List<Foo> Foos { get; private set; }
}

This will produce:

<FooParent>
  <Foos>
    <Foo xmlns="http://schemas.datacontract.org/2004/07/JezNamespace">
      <Field1>hello</Field1>
      <Field2>world</Field2>
    </Foo>
    ...

Alternatively, if you do not want that Foos intermediate element at all, you can replace XmlArrayItem in code above with XmlElement . In this case, the output XML will look like this:

<FooParent>
  <Foo xmlns="http://schemas.datacontract.org/2004/07/JezNamespace">
    <Field1>hello</Field1>
    <Field2>world</Field2>
  </Foo>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM