我搜索了几个小时,发现了类似的结果,但没有针对这个具体情况。请考虑以下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个数组,但看起来这应该是一件简单的事情。
答案 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>