这会将xml样本反序列化为" XmlModel"类。
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
namespace XmlTest
{
public class DeserializeXml
{
public XmlModel GetXmlModel()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<root>
<foo>
<bar>1</bar>
<bar>2</bar>
</foo>
</root>";
var dS = new XmlSerializer(typeof(XmlModel));
var m = new XmlModel();
using (var reader = new StringReader(xml))
{
return (XmlModel) dS.Deserialize(reader);
}
}
}
[XmlRoot("root")]
public class XmlModel
{
[XmlArray("foo")]
[XmlArrayItem("bar")]
public List<string> Foo { get; set; }
}
}
这将获得模型:
var d = new DeserializeXml();
result = d.GetXmlModel();
我正在使用遗留代码,除了更改XmlAttributes之外,我无法对XmlModel类进行更改。问题在于:实际的Xml没有&#34; foo&#34;节点:
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<root>
<bar>1</bar>
<bar>2</bar>
</root>";
所以现在我坚持让解串器吞下这个xml并输出类型XmlModel的任务。如果没有Xslt预处理或其他更复杂的方法,这可能吗?
答案 0 :(得分:1)
如果您对另一种反序列化方法持开放态度,那么这将有效。它应该与XmlSerializer
一样快,如果不是更快。它只是在原始xml上打开XmlReader
,移动到第一个“data”元素,将数据转储到列表中,然后填充并从中返回XmlModel
。
LINQPad文件可用here。
public XmlModel GetXmlModel()
{
string xml = @"<?xml version=""1.0"" encoding=""utf-16""?>
<root>
<bar>1</bar>
<bar>2</bar>
</root>";
using (var reader = XmlReader.Create(new StringReader(xml)))
{
reader.MoveToContent();
var data = new List<string>();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
var element = XNode.ReadFrom(reader) as XElement;
switch (element.Name.LocalName)
{
case "bar":
{
data.Add(element.Value);
break;
}
}
}
}
return new XmlModel() { Foo = data };
}
}
如果您的bar
类不仅仅是一个简单的内在类型,例如string
,那么这显然会变得更加复杂。
答案 1 :(得分:1)
您可以使用XmlAttributeOverrides
为XmlModel
指定备用XML属性,然后使用这些属性construct an XmlSerializer
执行以下操作:
var serializer = new XmlSerializer(typeof(XmlModel), overrides).
但请注意documentation:
中的以下警告为了提高性能,XML序列化基础结构动态生成程序集以序列化和反序列化指定的类型。基础结构查找并重用这些程序集。仅当使用以下构造函数时才会出现此问题:
XmlSerializer.XmlSerializer(类型):
XmlSerializer.XmlSerializer(类型,字符串)
如果使用任何其他构造函数,则会生成同一程序集的多个版本,并且永远不会卸载,这会导致内存泄漏和性能下降。最简单的解决方案是使用前面提到的两个构造函数之一。否则,您必须将程序集缓存在Hashtable ...
中
以下静态类创建并缓存2个序列化程序,一个用于XmlModel
的“当前”版本,另一个用于<bar>
元素缺少外部容器元素的“备用”版本:
public static class XmlModelSerializer<TRoot>
{
static XmlSerializer alternateSerializerInstance;
static XmlSerializer currentSerializerInstance;
public static XmlSerializer AlternateSerializerInstance { get { return alternateSerializerInstance; } }
public static XmlSerializer CurrentSerializerInstance { get { return currentSerializerInstance; } }
static XmlModelSerializer()
{
XmlAttributes alternateAttributes = new XmlAttributes
{
XmlElements = { new XmlElementAttribute("bar") },
};
XmlAttributeOverrides alternateOverrides = new XmlAttributeOverrides();
alternateOverrides.Add(typeof(XmlModel), "Foo", alternateAttributes);
alternateSerializerInstance = new XmlSerializer(typeof(TRoot), alternateOverrides);
XmlAttributes currentAttributes = new XmlAttributes
{
XmlArray = new XmlArrayAttribute("foo"),
XmlArrayItems = { new XmlArrayItemAttribute("bar") },
};
XmlAttributeOverrides currentOverrides = new XmlAttributeOverrides();
currentOverrides.Add(typeof(XmlModel), "Foo", currentAttributes);
currentSerializerInstance = new XmlSerializer(typeof(TRoot), currentOverrides);
}
}
通过使用两个不同的序列化程序,每个可能的XML格式一个,您可以避免对旧版XmlModel
类型进行任何更改。
然后,反序列化格式
的扁平化XML<root>
<bar>1</bar>
<bar>2</bar>
</root>
您只需:
var dS = XmlModelSerializer<XmlModel>.AlternateSerializerInstance;
using (var reader = new StringReader(xml))
{
return (XmlModel) dS.Deserialize(reader);
}
示例fiddle显示两种格式的反序列化。