简体   繁体   中英

Serialize a Nested List in c# to XML

I have a nested list in c# : List<List<OVReady.Types.PointF[]>> and it need to be serialize to xml

My code:

[XmlRoot("AlertInfo")]
public class AlertInfo
{
    [XmlElement("TargetID")]
    public string strTargetId { get; set; }

    [XmlElement("ChannelID")]
    public string strChId { get; set; }

    [XmlElement("Timestamp")]
    public string strTimestamp { get; set; }

    [XmlElement("Object")]
    public RectObject rfObject { get; set; }

    [XmlArray("Polygons")]
    [XmlArrayItem("Polygon")]
    public List<List<OVReady.Types.PointF[]>> lstPolygons { get; set; }
}

public class RectObject
{
    [XmlAttribute("x")]
    public float x { get; set; }
    [XmlAttribute("y")]
    public float y { get; set; }
    [XmlAttribute("width")]
    public float width { get; set; }
    [XmlAttribute("height")]
    public float height { get; set; }
}

What I get:

<AlertInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TargetID>730</TargetID>
  <ChannelID>613</ChannelID>
  <Timestamp>2014-09-26 19:56:07:5660</Timestamp>
  <Object x="0.24375" y="0.025" width="0.259375" height="0.9375001" />
  <Polygons>
    <Polygon>
      <ArrayOfPointF>
        <PointF>
          <X xmlns="http://www.objectvideo.com/schemas/ovready">0.30625</X>
          <Y xmlns="http://www.objectvideo.com/schemas/ovready">0.9375</Y>
        </PointF>
        <PointF>
          <X xmlns="http://www.objectvideo.com/schemas/ovready">0.696875</X>
          <Y xmlns="http://www.objectvideo.com/schemas/ovready">0.9416667</Y>
        </PointF>
      </ArrayOfPointF>
    </Polygon>
  </Polygons>
</AlertInfo>

What I want:

<AlertInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TargetID>730</TargetID>
  <ChannelID>613</ChannelID>
  <Timestamp>2014-09-26 19:56:07:5660</Timestamp>
  <Object x="0.24375" y="0.025" width="0.259375" height="0.9375001" />
  <Polygons>
    <Polygon>
        <Point x=0.30625 y=0.9375>
        <Point x=0.696875 y=0.9416667>
      </Polygon>
  </Polygons>
</AlertInfo>

How can I remove the tag and and set the position x and y as I want?

Let's start with the simplest approach possible. Redesigning your property to be simpler to serialize.

To be able to accomplish this i had to introduce a new class Polygon:

public class Polygon
{
    [XmlElement("Point")]
    public List<PointF> Points { get; set; }
}

And then you would have to redesign your property to be:

[XmlArray("Polygons")]
[XmlArrayItem("Polygon")]
public List<Polygon> lstPolygons { get; set; }

If you don't have the luxury to redesign that property like in this example, below you can find a hack that could work as well. It is not to clean but it works and it is simple.

The idea is to XmlIgnore your current attribute, to prevent the XML serializer from processing it, and then use one additional getter designed only for serialization that will re-format the data dynamically using LINQ to make it ready for the serializer. Check out the code:

[XmlRoot("AlertInfo")]
public class AlertInfo
{
    [XmlElement("TargetID")]
    public string strTargetId { get; set; }

    [XmlElement("ChannelID")]
    public string strChId { get; set; }

    [XmlElement("Timestamp")]
    public string strTimestamp { get; set; }

    [XmlElement("Object")]
    public RectObject rfObject { get; set; }

    [XmlIgnore]
    public List<List<PointF[]>> lstPolygons { get; set; }

    [XmlArray("Polygons")]
    [XmlArrayItem("Polygon")]
    public List<Polygon> Polygons
    {
        get {
            return lstPolygons.Select(p => new Polygon() { Points = p.SelectMany(lp => lp).ToList() }).ToList();
        }
    }
}

The result of serializing the above AlertInfo Polygons property is this:

<Polygons>
  <Polygon>
    <Point x="0" y="0" />
    <Point x="0" y="0" />
  </Polygon>
</Polygons>

An alternative approach is to implement IXmlSerializable and control the serialization yourself. Check out this article on how to do it:

http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

  1. You nested to much, remove the most nested array:

     public List<List<OVReady.Types.PointF[]>> lstPolygons { get; set; } 

    to

     public List<List<OVReady.Types.PointF>> lstPolygons { get; set; } 
    • if you can modify OVReady.Types.PointF class than decorate it to proper serialize its properties to the attributes instead of the new elements
    • if not, follow this answer

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