XmlArray有多个名字

时间:2018-04-09 19:55:32

标签: c# xml deserialization

我搜索了几个小时,发现了类似的结果,但没有针对这个具体情况。请考虑以下XML文件。

<root>
<largeImages>
    <largeImage>
        <url>./imageLarge.jpg</url>
        <height>480</height>
        <width>640</width>
    </largeImage>
</largeImages>
<smallImages>
    <smallImage>
        <url>./imageSmall.jpg</url>
        <height>240</height>
        <width>320</width>
    </smallImage>
</smallImages>
</root>

我要做的是将其反序列化为单个图像数组而不是2个数组。

public class root {
    [XmlArray("largeImages")]
    [XmlArrayItem("largeImage")]
    public image[] largeImages { get; set; }

    [XmlArray("smallImages")]
    [XmlArrayItem("smallImage")]
    public image[] smallImages { get; set; }
}

这个类让我得到2个数组。 root.largeImages和root.smallImages。由于我的应用程序不关心大图像或小图像,我想将其反序列化为单个数组root.images。我已经尝试过XmlArray,XmlArrayItem,XmlElement甚至XmlChoiceIdentifier的变体而没有任何成功。我正在考虑以下几行中无法编译的内容,因为显然每个属性只能使用一次XmlArrayAttribute。

[XmlArray("largeImages")]
[XmlArray("smallImages")]
[XmlArrayItem("largeImage")]
[XmlArrayItem("smallImage")]
public image[] images { get; set; }

显然,我可以在反序列化XML之后合并代码中的2个数组,但看起来这应该是一件简单的事情。

4 个答案:

答案 0 :(得分:1)

XPATH可能是你的答案,假设你并不真正关心将它映射到一个类。 XPath wildcards on node name举例说明了您如何选择多个项目 - http://csharp.net-tutorials.com/xml/using-xpath-with-the-xmldocument-class/举例说明了它在C#中的使用方式。

另一种可能使用XSLT的方法:使用代码:How to apply an XSLT Stylesheet in C#和像Combining elements from 2 lists in XSLT这样的XSLT可以得到你想要的东西。

我个人认为生活最简单,因为在这个例子中你看起来并不像中间数据结构是什么。

答案 1 :(得分:0)

简单!!!我一直这样做。诀窍是使用root,你需要使用Elements(),然后使用FirstOrDefault()只获得一个。

{{1}}

答案 2 :(得分:0)

鉴于 How to define multiple names for XmlElement field? 的答案主要用于不是数组的元素,最简单的解决方案似乎是为其中一个图像元素引入一个代理属性,比如{{1 }}:

<smallImages>

注意:

  • 反序列化为预先分配的public class root { [XmlArray("largeImages")] [XmlArrayItem("largeImage")] public List<image> Images { get; set; } = new List<image>(); [XmlArray("smallImages")] [XmlArrayItem("smallImage")] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)] public List<image> SmallImagesSurrogate { get { return Images; } } public bool ShouldSerializeSmallImagesSurrogate() { return false; } } 时,List<T>只会追加反序列化元素到现有列表。这样就可以将XmlSerializer<largeImages>中的元素连接到同一个集合中而不会丢失数据。

  • 代理财产必须是公开的,但可以制作&#34;不太明显&#34;通过设置[Browsable(false)]

  • 等属性 只要预先分配了集合,
  • <smallImages>就可以成功反序列化只获取集合属性。我利用这个来避免为代理人添加一个setter。

  • 如果您需要重新序列化XmlSerializer,方法root将阻止图像数组进行双序列化。 (有关原因的说明,请参阅 ShouldSerialize*() vs *Specified Conditional Serialization Pattern 。)相反,所有图片都会在ShouldSerializeSmallImagesSurrogate()下序列化。此方法不会影响反序列化。

示例工作.Net fiddle

答案 3 :(得分:0)

我在模型序列化方面遇到了挑战,感谢MSDN,我找到了答案。这是我的解决方案:

public class Document
{
    [XmlElement(ElementName = "seller_id")]
    public string SellerId { get; set; }

    [XmlArray(ElementName = "order_details")]
    [XmlArrayItem(Type = typeof(SgtinCode), ElementName = "sgtin")]
    [XmlArrayItem(Type = typeof(SsccCode), ElementName = "sscc")]
    public Code[] Codes { get; set; }
}

public abstract class Code
{
    [XmlText]
    public string Value { get; set; }
}

public class SgtinCode : Code
{ }

public class SsccCode : Code
{ }

模型设置:

var document = new Document
{
    SellerId = Guid.NewGuid().ToString(),
    Codes = new Code[]
    {
        new SsccCode { Value = "111700126101510000000000011" },
        new SsccCode { Value ="111700126101510000000000012" },
        new SsccCode { Value ="111700126101510000000000013" },
        new SgtinCode { Value = "abc" }
    }
}

和XML输出:

<?xml version="1.0" encoding="utf-8"?>
<documents>
  <foreign_shipment>
    <seller_id>fb2d35e7-c5d1-43ad-a272-89f897f41058</seller_id>
    <order_details>
      <sscc>111700126101510000000000011</sscc>
      <sscc>111700126101510000000000012</sscc>
      <sscc>111700126101510000000000013</sscc>
      <sgtin>abc</sgtin>
    </order_details>
  </foreign_shipment>
</documents>
相关问题