反序列化XML数组,其中根元素是数组且元素不遵循约定。

19

我获取的XML是由外部来源提供的,因此我没有轻松重新格式化它的能力。我想在我的实体上使用xml属性,而不是编写一个知道XML和实体格式的linq查询。这是一个例子:

<?xml version="1.0"?>
<TERMS>
    <TERM>
        <ID>2013-2</ID>
        <DESC>Spring 2013</DESC>
    </TERM>
    <TERM>
        <ID>2013-3</ID>
        <DESC>Summer 2013 Jun&amp;Jul</DESC>
    </TERM>
</TERMS>

我知道XMLSerializer期望的是ArrayOfTerm而不是TERMS,但我可以通过使用xml属性来调整实体以使用不同的元素名称,例如:
public class TermData
{
    [XmlArray("TERMS")]
    [XmlArrayItem("TERM")]
    public List<Term> terms;
}

public class Term
{
    [XmlElement("ID")]
    public string id;

    [XmlElement("DESC")]
    public string desc;
}

我正在这样反序列化数据:

TermData data;

XmlSerializer serializer = new XmlSerializer(typeof(TermData));
using (StringReader reader = new StringReader(xml))
{
   data = (TermData)serializer.Deserialize(reader);
}

return View(data.terms);

我面临的问题是TERMS既是根元素又是数组本身。如果XML有一个不是数组的根元素,我可以像这样编辑我的TermData类,并且反序列化将正确执行(已测试)。
[XmlRoot("ROOT")]
public class TermData
{
    [XmlArray("TERMS")]
    [XmlArrayItem("TERM")]
    public List<Term> terms;
}

请注意,将TERMS用作XMLRoot无效。现在,我的代码会抛出异常。
 InvalidOperationException: There is an error in XML document (2,2).
 InnerException: "<TERMS xmlns=" was not expected.

这让我相信XML格式不正确,但据我所知,我给出的例子是完全有效的XML。如果我可以编辑源XML,这一切都将变得微不足道,但可能会有大量类似的响应,我需要能够适应任何可能出现的情况。我试过几乎所有方法,却无法在不编辑XML的情况下对其进行反序列化。如果不必定义一个包装类(TermData)来保存列表,这也将非常方便,但这似乎只适用于XML遵循序列化程序的命名约定(ArrayOfTerm等)。

1
你的文件有多大?我遇到了类似的问题(尝试读取log4net XML文件),我的解决方法是加载XML,任意注入适当的根标签,然后从那里开始操作。 - Dillie-O
注入一个根元素可能是一个解决方案。我其实没有想到过,所以感谢建议。虽然这个问题似乎应该可以在不使用这种变通方法的情况下解决。 - pixelshaded
1个回答

24
也许你可以尝试:
[XmlRoot("TERMS")]
public class TermData
{
    public TermData()
     {
       terms = new List<Term>();
     }

    [XmlElement("TERM")]
    public List<Term> terms{get;set;}
}

public class Term
{
    [XmlElement("ID")]
    public string id{get;set;}

    [XmlElement("DESC")]
    public string desc{get;set;}
}

希望这可以帮到你,

尝试过这个,但它无法反序列化。TermData.terms 的计数为0。 - pixelshaded
@pixelshaded:为该类添加了一个公共构造函数,用于初始化列表。这应该会有所帮助。 - jbl
仍然得到一个空列表。 - pixelshaded
@pixelshaded 忽略了所有字段都应该是属性。我也更新了它。 - jbl
2
请注意,不需要为TermData和访问器编写构造函数。 - pixelshaded
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接