如何通过调用XmlSerializer.Serialize创建XmlNode?
我正在使用一个类库,该类库表示.xml中的某些配置。使用XmlSerializer读取配置。幸运的是,代表.xml的类使用XmlAnyElement
属性,通过该属性,我可以出于自己的目的扩展配置数据,而无需修改原始类库。
<?xml version="1.0" encoding="utf-8"?> <Config> <data>This is some data</data> <MyConfig> <data>This is my data</data> </MyConfig> </Config>
这非常适合反序列化。我能够允许类库像往常一样反序列化.xml,并且我可以将自己的XmlSerializer
实例与XmlNodeReader
一起用于内部XmlNode
。
public class Config { [XmlElement] public string data; [XmlAnyElement] public XmlNode element; } public class MyConfig { [XmlElement] public string data; } class Program { static void Main(string[] args) { using (Stream fs = new FileStream(@"c:\temp\xmltest.xml", FileMode.Open)) { XmlSerializer xser1 = new XmlSerializer(typeof(Config)); Config config = (Config)xser1.Deserialize(fs); if (config.element != null) { XmlSerializer xser2 = new XmlSerializer(typeof(MyConfig)); MyConfig myConfig = (MyConfig)xser2.Deserialize(new XmlNodeReader(config.element)); } } }
我需要创建一个实用程序,该实用程序将允许用户生成一个新的配置文件,其中包括类库配置以及我自己的配置,因此将创建未从.xml文件读取的新对象。问题是如何将数据序列化回.xml?
我意识到我必须首先在数据上调用XmlSerializer.Serialize
,然后再对类库配置调用相同的方法。但是,这要求我的数据在调用Serialize
之后由XmlNode
表示。使用XmlSerializer将对象序列化为XmlNode的最佳方法是什么?
谢谢,
凯文
顺便说一句,看起来像克里斯·洛维特(Chris Lovett)编写的XmlNodeWriter
类可从Microsoft一次获得,但现在链接已断开。有谁知道替代课程的位置吗?
解决方案
回答
因此,我们需要让类包含自定义配置信息,然后将该类序列化为XML,然后将该序列化的XML转换为XML节点:是吗?
我们能否只接受XMLSerializer创建的字符串并将其包装在它自己的XML标记中?
XmlSerializer xs = new XmlSerializer(typeof(MyConfig)); StringWriter xout = new StringWriter(); xs.Serialize(xout, myConfig); XmlDocument x = new XmlDocument(); x.LoadXml("<myConfig>" + xout.ToString() + "</myConfig>");
现在,x是一个XmlDocument,其中包含一个元素" <myconfig>",其中包含序列化自定义配置。
这就是我们要找的东西吗?
回答
一种解决方案是将内部对象序列化为字符串,然后将该字符串加载到XmlDocument中,我们可以在其中找到表示数据的XmlNode并将其添加到外部对象。
XmlSerializer xser1 = new XmlSerializer(typeof(Config)); XmlSerializer xser2 = new XmlSerializer(typeof(MyConfig)); MyConfig myConfig = new MyConfig(); myConfig.data = "My special data"; StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); XmlWriter xw = new XmlTextWriter(sw); xser2.Serialize(xw, myConfig); XmlDocument doc = new XmlDocument(); doc.LoadXml(sb.ToString()); Config config = new Config(); config.data = "some new info"; config.element = doc.LastChild; xser1.Serialize(fs, config);
但是,这种解决方案很麻烦,我希望有更好的方法,但是现在可以解决我的问题。
现在,只要我能在几个博客上找到神话般的XmlNodeWriter即可!
回答
至少有一个资源指出了此作为XmlNodeWriter的替代方法:http://msdn.microsoft.com/en-us/library/5x8bxy86.aspx。否则,我们可以使用它们在寻找XmlNodeWriter的GotDotNet的新MSDN代码库替代品上使用的格式编写MS。
回答
它花了一些时间,但是XPathNavigator路由确实起作用了……只记得在XmlWriter上调用.Close,.Flush()不会做任何事情:
//DataContractSerializer serializer = new DataContractSerializer(typeof(foo)); XmlSerializer serializer = new XmlSerializer(typeof(foo)); XmlDocument doc = new XmlDocument(); XPathNavigator nav = doc.CreateNavigator(); XmlWriter writer = nav.AppendChild(); writer.WriteStartDocument(); //serializer.WriteObject(writer, new foo { bar = 42 }); serializer.Serialize(writer, new foo { bar = 42 }); writer.WriteEndDocument(); writer.Flush(); writer.Close(); Console.WriteLine(doc.OuterXml);