我该如何在C#中XML反序列化一个数组的数组?

3

我正在尝试反序列化信用卡BIN对象,以便在表单上进行品牌验证,但无法正确完成。要么内部对象无法反序列化,要么主品牌列表变为空值。有人可以帮我一下吗?

我的XML文件如下:

<?xml version="1.0" encoding="utf-8"?>
<Brands>
  <Brand type="visa">
    <Bins>
      <Bin enabled="true" value="123" />
      <Bin enabled="true" value="456" />
      <Bin enabled="true" value="789" />
    </Bins>
  </Brand>
  <Brand type="master">
    <Bins>
      <Bin enabled="true" value="987" />
      <Bin enabled="true" value="654" />
      <Bin enabled="true" value="321" />
    </Bins>
  </Brand>
</Brands>

我最新的代码(将brandsCollection设置为null)如下:

[XmlRoot("Brands")]
public class CreditCardBrand
{
    [XmlArray("Brands"), XmlArrayItem("Brand")]
    public CreditCardBrandCollection[] brandsCollection { get; set; }
}

public class CreditCardBrandCollection
{
    [XmlElement("Bins")]
    public CreditCardBrandBins[] binsCollection { get; set; }

    [XmlAttribute("type")]
    public CreditCardBrands brand { get; set; }
}

public class CreditCardBrandBins
{
    [XmlAttribute("value")]
    public string bin { get; set; }

    [XmlAttribute("enabled")]
    public bool enabled { get; set; }
}

我希望将这个XML反序列化为品牌数组,每个品牌都有一个名称(类型)属性和与之关联的一组桶(仅启用的桶),以便在系统启动时将其放入内存中。

2个回答

2

其实很简单,你只是混淆了根元素声明和brandsCollection数组属性的方式。你需要按照以下方式更改声明:

[XmlRoot("Brands")]
public class CreditCardBrand
{
    [XmlElement("Brand")]
    public CreditCardBrandCollection[] brandsCollection { get; set; }
}

这里的[XmlElement]会使数组中的每个元素都用一个<Brand>标签来表示。在您原来的代码中,您描述了一个XML,它应该看起来像这样:
<Brands>
    <Brands> <!-- duplicate Brands element here -->
        <Brand type="…"></Brand>
        <Brand type="…"></Brand>
        <Brand type="…"></Brand></Brands>
</Brands>

谢谢反馈,Ondrej...我想放弃这个实现,像L.B建议的那样直接使用普通的Linq2XML会更容易。 - leobelones

2

如果您想使用Linq2Xml

XDocument xDoc = XDocument.Parse(xml); //or XDocument.Load(filename)
List<CreditCardBrand> brands =
            xDoc.Descendants("Brand")
            .Select(br => new CreditCardBrand()
            {
                Type = br.Attribute("type").Value,
                Bins = br.Descendants("Bin")
                            .Select(b => new CreditCardBin(){
                                Enabled = (bool)b.Attribute("enabled"),
                                Value = b.Attribute("value").Value,
                            }).Where(b => b.Enabled == true)
                            .ToList()

            })
            .ToList();

--

public class CreditCardBrand
{
    public string Type { get; set; }
    public List<CreditCardBin> Bins { get; set; }
}

public class CreditCardBin
{
    public string Value { get; set; }
    public bool Enabled { get; set; }
}

实际上,我只是在第二个选择中添加了一个where子句,以便它只带来启用的存储箱。除此之外,一切都很准确!再次感谢! - leobelones
@leobelones 是的,我错过了“(仅启用的)”。 - L.B

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