我想调用XmlSerializer.Deserialize
传递XDocument
。它可能需要Stream
,XmlReader
或TextReader
。
我是否可以从XDocument
生成以上其中一项而不实际将XDocument
转储到某个中间商店,例如MemoryStream
?
似乎我所追求的是XmlReader
的实现与XDocument
一起使用。我找不到一个。
答案 0 :(得分:48)
您可以使用XDocument.CreateReader()
创建一个XmlReader
来读取XDocument
的内容。
同样,以下内容也适用。
XmlReader GetReader(XDocument doc)
{
return doc.Root.CreateReader();
}
答案 1 :(得分:12)
这是一个将对象序列化和反序列化到XDocument中的实用程序。
XDocument doc = SerializationUtil.Serialize(foo);
Foo foo = SerializationUtil.Deserialize<Foo>(doc);
这是班级:
public static class SerializationUtil
{
public static T Deserialize<T>(XDocument doc)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (var reader = doc.Root.CreateReader())
{
return (T)xmlSerializer.Deserialize(reader);
}
}
public static XDocument Serialize<T>(T value)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
XDocument doc = new XDocument();
using (var writer = doc.CreateWriter())
{
xmlSerializer.Serialize(writer, value);
}
return doc;
}
}
答案 2 :(得分:4)
(Steve Guidi回答的附录)
据我所知,没有XmlReader
的实现,您可以轻松地使用XDocument
而不通过中间存储移动XML内容,如XML的字符串表示和支持所有类型,例如System.Xml.XmlNodeReader
支持。
由XDocument.CreateReader
(一个System.Xml.Linq.XNodeReader
,一个内部类)返回的阅读器是XmlReader
,适用于大多数Xml文档,但不适用于具有二进制数据元素的文档,因为它实施does not support Base64 or BinHex data:
不支持Base64和BinHex数据。如果您尝试检索 这些类型的数据(例如,通过调用 ReadElementContentAsBase64),读者将抛出 NotSupportedException异常。
与XDocument.CreateReader().CanReadBinaryContent
形成鲜明对比的是,此false
System.Xml.XmlNodeReader
为public class SomeTest
{
public byte[] BinaryTest { get; set; }
}
class Program
{
static void Main(string[] args)
{
XDocument document = new XDocument(
new XElement("SomeTest",
new XElement("BinaryTest", "VGVzdA==")));
using (var reader = document.CreateReader())
{
var serializer = new XmlSerializer(typeof(SomeTest));
var someTest = serializer.Deserialize(reader) as SomeTest;
// NotSupportedException here (as inner exception)
}
}
}
。
例如,该程序抛出异常:
string
但是,将XML解压缩为TextReader
并将其作为 using (var reader = new StringReader(document.ToString()))
传递到序列化程序中:
XDocument
如果有另一种方法来反序列化包含二进制数据的{{1}}而不将其首先转换为字符串,我也会感兴趣。
答案 3 :(得分:0)
我想在创建XmlReader后添加它,即:
XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
XmlReader reader = xmlDocumentToDeserialize.CreateReader();
然后你应该打电话:
reader.MoveToContent();
因为否则读者不会“指向”第一个节点,导致空读者出现!然后你可以安全地调用反序列化:
MyObject myObject = (MyObject)serializer.Deserialize(reader);
答案 4 :(得分:0)
我喜欢@Simon_Weaver的答案。基于此,这是我的总结:
using System;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace XDocSerialization
{
[TestClass]
public class Tests
{
[TestMethod]
public void Tests_SerializeToXDoc()
{
var sheep = new Animal
{
Name = "Sheep", Legs = 4, Nutrition = Nutrition.Herbivore
};
var xdoc = sheep.SerializeToXDoc();
var ser = "<Animal " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n " +
"<Name>Sheep</Name>\r\n <Legs>4</Legs>\r\n " +
"<Nutrition>Herbivore</Nutrition>\r\n</Animal>";
Assert.AreEqual(xdoc.ToString(), ser);
Assert.IsInstanceOfType(xdoc, typeof(XDocument));
}
[TestMethod]
public void Tests_DeserializeFromXDoc()
{
var Sheep = new Animal
{
Name = "Sheep", Legs = 4, Nutrition = Nutrition.Herbivore
};
var des = Sheep.SerializeToXDoc().DeserializeFromXDoc<Animal>();
Assert.AreEqual(des.Name, Sheep.Name);
Assert.AreEqual(des.Nutrition, Sheep.Nutrition);
Assert.AreEqual(des.Legs, Sheep.Legs);
Assert.AreNotSame(des, Sheep);
}
}
public static class ExtensionMethods
{
public static T DeserializeFromXDoc<T>(this XDocument source)
{
if (source == null || source.Root == null)
return default(T);
using (var reader = source.Root.CreateReader())
return (T)new XmlSerializer(typeof(T)).Deserialize(reader);
}
public static XDocument SerializeToXDoc<T>(this T source)
{
if (source == null)
return null;
var doc = new XDocument();
using (var writer = doc.CreateWriter())
new XmlSerializer(typeof(T)).Serialize(writer, source);
return doc;
}
}
[Serializable]
public class Animal
{
public string Name { get; set; }
public int Legs { get; set; }
public Nutrition Nutrition { get; set; }
}
public enum Nutrition
{
Herbivore,
Carnivore,
Omnivore
}
}