Xml序列化/反序列化索引条目

时间:2014-06-25 19:06:08

标签: c# xml asp.net-mvc-3 serialization xsd

我有一个带索引条目的xml文件,如:

<xml>
   <entry1>
   ...
   </entry1>
   <entry2>
   ...
   </entry2>
</xml>

我使用xsd工具生成模式,然后使用c#类,显然它已创建:

public partial class entry1
...
public partial class entry2

如何更改类,以便在我运行序列化/反序列化时,它将识别并将它们命名为条目&#39; n&#39;在xml和我的对象中?

我需要使用相同类型的无限条目,并且无法更改xml。

1 个答案:

答案 0 :(得分:1)

鉴于您无法更改XML,您将无法使用xsd.exe为此XML生成类。 XmlSerializer<entry1><entry2>,... <entryN>等任意命名的元素没有内置支持。您可以在根类中实施IXmlSerializable,从而启用XmlSerializer来调用自定义(反)序列化代码,也可以使用XmlDocumentXmlReader或(我的推荐) )XDocument直接读取XML,如果您认为有必要,构建一个对象模型。

ASIDE:如果可能,请反击此API。这违反了良好的XML设计。 XML是由它的自然顺序。 XML阅读<entry1/><entry2/>...<entryN/>应该只是<entry/><entry/>...<entry/>。 XML中的位置表示序列。

编辑:根据OP的评论,我将添加此内容。如果您的XML非常大,执行字符串替换可能不是最佳解决方案。您可以创建XmlReader的子类,将<entryN>元素替换为<entry>个元素。您只需要覆盖LocalName属性。请注意,我还没有安全&#34;这里 - 任何以&#34;条目&#34;开头的元素或属性将其名称更改为&#34; entry&#34;。我会留给你,以确定这是否足够你。如果没有,则在替换名称之前,当然可以执行其他状态检查(例如,确保您对某个元素进行了检查)。

// This class implements the LocalName override
private class CustomXmlReader : CustomXmlReaderBase
{
    // constructor
    public CustomXmlReader(XmlReader inner)
        : base(inner)
    {
    }

    // LocalName override
    public override string LocalName
    {
        get { return base.LocalName.StartsWith("entry") ? "entry" : base.LocalName; }
    }
}

// This class implements base behavior for an XML reader that wraps another XML reader.
private abstract class CustomXmlReaderBase : XmlReader
{
    protected CustomXmlReaderBase(XmlReader inner)
    {
        _inner = inner;
    }

    private readonly XmlReader _inner;

    public override string GetAttribute(string name)
    {
        return _inner.GetAttribute(name);
    }

    public override string GetAttribute(string name, string namespaceURI)
    {
        return _inner.GetAttribute(name, namespaceURI);
    }

    public override string GetAttribute(int i)
    {
        return _inner.GetAttribute(i);
    }

    public override bool MoveToAttribute(string name)
    {
        return _inner.MoveToAttribute(name);
    }

    public override bool MoveToAttribute(string name, string ns)
    {
        return _inner.MoveToAttribute(name, ns);
    }

    public override bool MoveToFirstAttribute()
    {
        return _inner.MoveToFirstAttribute();
    }

    public override bool MoveToNextAttribute()
    {
        return _inner.MoveToNextAttribute();
    }

    public override bool MoveToElement()
    {
        return _inner.MoveToElement();
    }

    public override bool ReadAttributeValue()
    {
        return _inner.ReadAttributeValue();
    }

    public override bool Read()
    {
        return _inner.Read();
    }

    public override string LookupNamespace(string prefix)
    {
        return _inner.LookupNamespace(prefix);
    }

    public override void ResolveEntity()
    {
        _inner.ResolveEntity();
    }

    public override XmlNodeType NodeType
    {
        get { return _inner.NodeType; }
    }

    public override string LocalName
    {
        get { return _inner.LocalName; }
    }

    public override string NamespaceURI
    {
        get { return _inner.NamespaceURI; }
    }

    public override string Prefix
    {
        get { return _inner.Prefix; }
    }

    public override string Value
    {
        get { return _inner.Value; }
    }

    public override int Depth
    {
        get { return _inner.Depth; }
    }

    public override string BaseURI
    {
        get { return _inner.BaseURI; }
    }

    public override bool IsEmptyElement
    {
        get { return _inner.IsEmptyElement; }
    }

    public override int AttributeCount
    {
        get { return _inner.AttributeCount; }
    }

    public override bool EOF
    {
        get { return _inner.EOF; }
    }

    public override ReadState ReadState
    {
        get { return _inner.ReadState; }
    }

    public override XmlNameTable NameTable
    {
        get { return _inner.NameTable; }
    }
}