代码之家  ›  专栏  ›  技术社区  ›  Kevin

如何从对XmlSerializer.Serialize的调用创建XmlNode?

  •  11
  • Kevin  · 技术社区  · 18 年前

    我正在使用一个类库,它在.xml中表示它的一些配置。使用 XmlSerializer 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,并且可以使用我自己的 具有 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 在类库配置上调用相同的方法之前,请在我的数据上。但是,这要求我的数据由 XmlNode 打完电话 Serialize . 将对象序列化为对象的最佳方式是什么 使用 XmlSerializer ?

    谢谢

    -凯文

    顺便说一句,它看起来像一个 XmlNodeWriter Chris Lovett编写的类曾在Microsoft提供,但现在链接已断开。有人知道有没有其他地方可以上这门课吗?

    4 回复  |  直到 14 年前
        1
  •  13
  •   Ed Schwehm    17 年前

    所以您需要让您的类包含自定义配置信息,然后将该类序列化为XML,然后将序列化后的XML转换为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是一个包含一个元素“<myconfig>”的XmlDocument,其中包含您的序列化自定义配置。

    这就是你想要的吗?

        2
  •  3
  •       17 年前

    这需要一些工作,但是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);
    
        3
  •  0
  •   Kevin    18 年前

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

    然而,这个解决方案很麻烦,我希望有更好的方法,但现在它解决了我的问题。

        4
  •  0
  •   Ed Schwehm    18 年前

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