内部元素的XML反序列化

时间:2012-08-03 16:37:27

标签: c# .net xml serialization deserialization

是否可以将内部xml元素反序列化为其等效类?我有以下xml片段:

<?xml version="1.0" encoding="utf-8" ?>
<tileconfiguration xmlns="http://somenamespace/tile-configuration">
   <tile top_left_x="3" top_left_y="1" bottom_right_x="38" bottom_right_y="48">
     <child>
     </child>
   </tile>
</tileconfiguration>

和代表<tile />元素的等效类:

[System.Xml.Serialization.XmlRoot(ElementName = "tile")]
public class Tile : System.Xml.Serialization.IXmlSerializable
{
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        throw new NotImplementedException();
    }
}

问题是,每当我尝试反序列化<tile /><tile_configuration />的实例时,XML反序列化器会在文档(2,2)中抛出错误。

        System.Xml.Serialization.XmlSerializer serial = new System.Xml.Serialization.XmlSerializer(typeof(Tile));
        System.IO.TextReader t = new System.IO.StreamReader("c:\\temp\\deserial.xml");
        Tile q = (Tile)serial.Deserialize(t);

如果我创建一个类来表示<tile_configuration />并直接从中反序列化,那么它运行正常,调试器会在ReadXml类上输入TileConfiguration方法,然后我可以从中管理解析子<tile />(和后代)元素 - 但这需要每次都重新读取整个xml文件。

简而言之;我是否需要读取和写入整个XML文件 - 每次我想使用序列化/反序列化时从root xml元素开始,或者是否有办法允许我忽略极端的外部元素并直接将相关的子xml元素反序列化为没有解析器chucking错误的代码等价?

很有责任。

3 个答案:

答案 0 :(得分:0)

是。一个想法是加载xml并使用Xpath查询选择所需的节点。然后反序列化由查询结果表示的xml。

答案 1 :(得分:0)

如果你想忽略外部元素并拥有完全控制和低开销的快速实现,我建议不要使用XMLSerializer,而是分别使用XmlReaderXmlWriter

您还可以通过使用XmlReader构建中间DOM并使用XMLSerializer将DOM写入输出文件来实现组合方法。

答案 2 :(得分:0)

鉴于您对XML的展示,没有必要实现IXmlSerializable。你可以试试这个:

[XmlRoot("tileconfiguration")]
public class TileConfiguration
{
    [XmlElement("tile")]
    public List<Tile> Tiles { get; set; }
}

[XmlRoot("tile")]
public class Tile
{
    [XmlAttribute("top_left_x")]
    public int TopLeftX { get; set; }

    [XmlAttribute("top_left_y")]
    public int TopLeftY { get; set; }

    [XmlAttribute("bottom_right_x")]
    public int BottomRightX { get; set; }

    [XmlAttribute("bottom_right_y")]
    public int BottomRightY { get; set; }

    [XmlElement("child")]
    public List<Child> children { get; set; }
}

[XmlRoot("child")]
public class Child
{
}

XmlSerializer serializer = XmlSerializer(typeof(TileConfiguration));
TileConfiguration tileConfiguration = (TileConfiguration)serializer.Deserialize(stream);

您还可以使用XmlReader来获取所需的元素:

List<Tile> tiles = new List<Tile>();
XmlSerializer serializer = XmlSerializer(typeof(Tile));

using (XmlTextReader xr = new XmlTextReader(xmlStream))
{
    while (!xr.EOF)
    {
        xr.MoveToContent();
        xr.ReadToDescendant("tile");

        if (xr.Name == "tile")
        {
            string tileXml = xr.ReadOuterXml();
            using (StringReader tileReader = new StringReader(tileXml))
            {
                Tile tile = (Tile)serializer.Deserialize(tileReader);
                tiles.Add(Tile);
            }
        }
        else
        {
            xr.ReadEndElement();
        }
    }
}