XML包装的集合不反序列化

时间:2013-06-04 09:28:48

标签: c# .net xml deserialization

我有以下格式的XML:

<PurchaseItem>
    <Name>Item 1</Name>
    <Costs>
        <Cost>
            <Code>A</Code>
            <Info>Test 1</Info>
        </Cost>
        <Cost>
            <Code>B</Code>
            <Info>Test 1</Info>
        </Cost>
        <Cost>
            <Code>C</Code>
            <Info>Test 1</Info>
        </Cost>
    </Costs>
</PurchaseItem>

我希望将此XML反序列化到以下类中:

public class PurchaseItem
{
    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlElement("Costs")]
    public Cost[] Costs { get; set; } 
}

public class Cost
{
    [XmlElement("Code")]
    public string Code{ get; set; }

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

然而,除非我让另一个类成为Cost[]的包装器,否则我似乎无法使其工作。 如何在PurchaseItem类中序列化成本数组,如上面的代码?

2 个答案:

答案 0 :(得分:3)

您正在定义一个数组,您应该使用[XmlArray]属性:)

[Serializable]
public class Cost
{
    [XmlElement("Code")]
    public string Code { get; set; }

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

[Serializable]
public class PurchaseItem
{
    [XmlElement("Name")]
    public string Name { get; set; }

    // XmlArray of Cost
    [XmlArray(ElementName = "Costs")]
    public Cost[] Costs { get; set; }
}

public class Tests
{

    [Test]
    public void Test()
    {
        var serializer = new XmlSerializer(typeof (PurchaseItem));

        var xml = @"<PurchaseItem>
                        <Name>Item 1</Name>
                        <Costs>
                            <Cost>
                                <Code>A</Code>
                                <Info>Test 1</Info>
                            </Cost>
                            <Cost>
                                <Code>B</Code>
                                <Info>Test 1</Info>
                            </Cost>
                            <Cost>
                                <Code>C</Code>
                                <Info>Test 1</Info>
                            </Cost>
                        </Costs>
                    </PurchaseItem>";

        var data = Encoding.UTF8.GetBytes(xml);
        var reader = XmlReader.Create(new MemoryStream(data));
        var item = (PurchaseItem) serializer.Deserialize(reader);

        Assert.AreEqual(item.Costs[0].Code, "A");
        Assert.AreEqual(item.Costs[1].Code, "B");
        Assert.AreEqual(item.Costs[2].Code, "C");
    }

}

答案 1 :(得分:2)

那是因为您在Costs数组上设置了属性[XmlElement]。在任何情况下,您都应该将属性[XmlArray]与数组或集合元素一起使用。这使您可以更改生成的XML中的集合元素的名称。 (有关XmlArray attribute here

的更多信息

但是,序列化程序提供了您正在查找的功能,而无需任何属性。有这个课程:

public class PurchaseItem
{
    [XmlElement("Name")]
    public string Name { get; set; }

    public Cost[] Costs { get; set; }
}

将为您提供以下Xml:

<?xml version="1.0" encoding="utf-16"?>
<PurchaseItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Foo</Name>
  <Costs>
    <Cost>
      <Code>C#</Code>
      <Info>Awesome</Info>
    </Cost>
    <Cost>
      <Code>VB6</Code>
      <Info>:(</Info>
    </Cost>
  </Costs>
</PurchaseItem>

只有在您想要更改集合的生成方式时,才需要添加[XmlArray]属性。例如,如果您希望将包含成本元素的节点命名为“FooCosts”,则需要:

public class PurchaseItem
{
    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlArray("FooCosts")]
    public Cost[] Costs { get; set; }
}

<?xml version="1.0" encoding="utf-16"?>
<PurchaseItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>Foo</Name>
  <FooCosts>
    <Cost>
      <Code>C#</Code>
      <Info>Awesome</Info>
    </Cost>
    <Cost>
      <Code>VB6</Code>
      <Info>:(</Info>
    </Cost>
  </FooCosts>
</PurchaseItem>