XML Serialization - Disable rendering root element

2019-01-03 05:22发布

Can I somehow disable rendering of root element of collection?

This class with serialization attributes:

[XmlRoot(ElementName="SHOPITEM", Namespace="")]
public class ShopItem
{
    [XmlElement("PRODUCTNAME")]
    public string ProductName { get; set; }       

    [XmlArrayItem("VARIANT")]
    public List<ShopItem> Variants { get; set; }
}

generates this XML:

<SHOPITEM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <PRODUCTNAME>test</PRODUCTNAME>
      <Variants>
          <VARIANT>
              <PRODUCTNAME>hi 1</PRODUCTNAME>
          </VARIANT>
          <VARIANT>
              <PRODUCTNAME>hi 2</PRODUCTNAME>
          </VARIANT>           
      </Variants>        
</SHOPITEM>

I don't want <Variants> element here. What must I do?

Also I don't need xsi and xsd namespaces in root element...

3条回答
虎瘦雄心在
2楼-- · 2019-01-03 06:05

To disable rendering of root element of collection, you must replace the attribute [XmlArrayItem] with [XmlElement] in your code.

For removing the xsi and xsd namespaces, create an XmlSerializerNamespaces instance with an empty namespace and pass it when you need to serialize your object.

Take a look on this example:

[XmlRoot("SHOPITEM")]
public class ShopItem
{
    [XmlElement("PRODUCTNAME")]
    public string ProductName { get; set; }

    [XmlElement("VARIANT")] // was [XmlArrayItem]
    public List<ShopItem> Variants { get; set; }
}

// ...

ShopItem item = new ShopItem()
{
    ProductName = "test",
    Variants    = new List<ShopItem>()
    {
        new ShopItem{ ProductName = "hi 1" },
        new ShopItem{ ProductName = "hi 2" }
    }
};

// This will remove the xsi/xsd namespaces from serialization
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");

XmlSerializer ser = new XmlSerializer(typeof(ShopItem));
ser.Serialize(Console.Out, item, ns);  // Inform the XmlSerializerNamespaces here

I got this output:

<?xml version="1.0" encoding="ibm850"?>
<SHOPITEM>
  <PRODUCTNAME>test</PRODUCTNAME>
  <VARIANT>
    <PRODUCTNAME>hi 1</PRODUCTNAME>
  </VARIANT>
  <VARIANT>
    <PRODUCTNAME>hi 2</PRODUCTNAME>
  </VARIANT>
</SHOPITEM>
查看更多
等我变得足够好
3楼-- · 2019-01-03 06:08

I don't believe it is possible to remove this element using the default xml serialization (with attributes). If you could do this, then serializing your ShopItem class would result in badly formed xml (no root element) for the object, which is not allowed.

What you can do however, is manually implement IXmlSerializable. This will give you the sort of fine-grained control you a re after.

[Edit] - sorry - misread that you were trying to remove Variants, not SHOPITEM. To remove the List "outer" element, just mark it up with an [XmlElement] attribute rather than an [XmlArrayItem] attribute. This will cause the list entries to just use the specified element name, without wrapping the list in an outer element.

For removing the namespaces, this is controlled by the seriliazer itself, not the markup on the class. I've just noticed that while I've updated this answer, Rubens Farias has provided an reply that shows you how to eliminate the namespace.

查看更多
不美不萌又怎样
4楼-- · 2019-01-03 06:09

Replace [XmlArrayItem("VARIANT")] with [XmlElement("VARIANT")].

查看更多
登录 后发表回答