我有两个XML文件,如下所示
格式1:
<Template Type="Print">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>
格式2:
<Templates>
<Template Type="Print">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>
<Template Type="Print">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>
</Templates>
我已经为格式1创建了Mapping Class,如下所示:
public class Template
{
private double _printWidth;
private double _printHeight;
/// <summary>
/// Print width in inches
/// </summary>
[System.Xml.Serialization.XmlAttributeAttribute()]
public double PrintWidth {
get {
return this._printWidth;
}
set {
this._printWidth = value;
this.RaisePropertyChanged("PrintWidth");
}
}
[System.Xml.Serialization.XmlAttributeAttribute()]
public double PrintHeight {
get {
return this._printHeight;
}
set {
this._printHeight = value;
this.RaisePropertyChanged("PrintHeight");
}
}
}
我想仅希望将格式2中具有Type="Print"
的单个节点的XML转换为Template
类。有没有通用的方法可以将XML文件(Foarmat 1和格式2的单个节点)反序列化为Template
类?
答案 0 :(得分:0)
是的,可以将Linq to XML与XmlSerializer
:
将XML加载到XDocument
使用linq在XML元素层次结构中查找具有适当属性的适当元素。
反序列化所选元素,使用XElement.CreateReader()
传递一个XmlReader
,将元素及其后代读取到序列化程序。
因此,例如:
public static void Test()
{
string xml1 = @"<Template Type=""Print"">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>";
string xml2 = @"<Templates>
<Template Type=""Print"">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>
<Template Type=""Print"">
<PrintWidth>7</PrintWidth>
<PrintHeight>5</PrintHeight>
</Template>
</Templates>";
var template1 = ExtractTemplate(xml1);
var template2 = ExtractTemplate(xml2);
Debug.Assert(template1 != null && template2 != null
&& template1.PrintWidth == template2.PrintWidth
&& template1.PrintWidth == 7
&& template1.PrintHeight == template2.PrintHeight
&& template1.PrintHeight == 5); // No assert
}
public static Template ExtractTemplate(string xml)
{
// Load the XML into an XDocument
var doc = XDocument.Parse(xml);
// Find the first element named "Template" with attribute "Type" that has value "Print".
var element = doc.Descendants("Template").Where(e => e.Attributes("Type").Any(a => a.Value == "Print")).FirstOrDefault();
// Deserialize it to the Template class
var template = (element == null ? null : element.Deserialize<Template>());
return template;
}
使用扩展方法:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XContainer element)
{
return element.Deserialize<T>(new XmlSerializer(typeof(T)));
}
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer)
{
using (var reader = element.CreateReader())
{
object result = serializer.Deserialize(reader);
if (result is T)
return (T)result;
}
return default(T);
}
}
顺便提一下,您的Template
类有一个错误:您需要使用PrintWidth
而不是PrintHeight
标记[XmlElement]
和[XmlAttribute]
以正确反序列化该XML:
public class Template
{
private double _printWidth;
private double _printHeight;
/// <summary>
/// Print width in inches
/// </summary>
[System.Xml.Serialization.XmlElementAttribute()]
public double PrintWidth
{
get
{
return this._printWidth;
}
set
{
this._printWidth = value;
this.RaisePropertyChanged("PrintWidth");
}
}
[System.Xml.Serialization.XmlElementAttribute()]
public double PrintHeight
{
get
{
return this._printHeight;
}
set
{
this._printHeight = value;
this.RaisePropertyChanged("PrintHeight");
}
}
}