【问题标题】:XML wrapped collection not deserializingXML 包装的集合不反序列化
【发布时间】:2013-06-04 09:28:47
【问题描述】:

我有一些格式如下的 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 类中序列化成本数组?

【问题讨论】:

  • 谢谢,Patrick 和 Daniel 的答案都是正确的!
  • 额外问题:如果我要将 xml 中的 xml 数组元素名称更改为 <foocost> 我如何在 c# 类中指定该更改? (它是Cost 类的属性)
  • [XmlArray(ElementName = "FooCosts")] [XmlArrayItem(ElementName="FooCost")] public Cost[] Costs { get; set; }

标签: c# .net xml deserialization


【解决方案1】:

你正在定义一个数组,你应该使用[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");
    }

}

【讨论】:

    【解决方案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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多