【问题标题】:How do I create an XmlNode from a call to XmlSerializer.Serialize?如何通过对 XmlSerializer.Serialize 的调用创建 XmlNode?
【发布时间】:2010-09-07 23:00:46
【问题描述】:

我正在使用一个类库,它在 .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 获得,但现在链接已损坏。有谁知道其他可以上这门课的地方吗?

【问题讨论】:

    标签: c# xml


    【解决方案1】:

    所以你需要让你的类包含自定义配置信息,然后将该类序列化为 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,其中包含您的序列化自定义配置。

    这就是你要找的东西吗?

    【讨论】:

      【解决方案2】:

      这需要做一些工作,但 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);
      

      【讨论】:

      • doc.DocumentElement 返回所需的XmlNode
      【解决方案3】:

      一种解决方案是将内部对象序列化为字符串,然后将字符串加载到 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!

      【讨论】:

        【解决方案4】:

        至少有一个资源指向此作为 XmlNodeWriter 的替代方案:http://msdn.microsoft.com/en-us/library/5x8bxy86.aspx。否则,您可以使用他们在新的 MSDN 代码库替代 GotDotNet 上寻找 XmlNodeWriter 的形式编写 MS。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-04
          • 2013-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多