Как создать XmlNode из вызова XmlSerializer.Serialize? - PullRequest
12 голосов
/ 05 сентября 2008

Я использую библиотеку классов, которая представляет некоторые ее конфигурации в .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 для своих данных, прежде чем вызывать тот же метод в конфигурации библиотеки классов. Однако для этого необходимо, чтобы мои данные были представлены XmlNode после вызова Serialize. Каков наилучший способ сериализации объекта в XmlNode с использованием XmlSerializer?

Спасибо

* 1023 Кевин *

btw-- Похоже, класс XmlNodeWriter, написанный Крисом Ловеттом, был когда-то доступен от Microsoft, но теперь ссылки не работают. Кто-нибудь знает альтернативное место, чтобы получить этот класс?

Ответы [ 4 ]

11 голосов
/ 05 сентября 2008

Итак, вам нужно, чтобы ваш класс содержал пользовательскую информацию о конфигурации, затем сериализовал этот класс в 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, содержащий один элемент, "", в котором есть ваша персонализированная конфигурация.

Это то, что вы ищете?

3 голосов
/ 21 ноября 2008

Это заняло немного работы, но маршрут XPathNavigator действительно работает ... просто не забудьте вызвать. Закройте на XmlWriter, .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);
0 голосов
/ 05 сентября 2008

По крайней мере один ресурс указывает на это как альтернативу XmlNodeWriter: http://msdn.microsoft.com/en-us/library/5x8bxy86.aspx. В противном случае вы могли бы написать MS, используя ту форму, которую они имеют в новой замене библиотеки кодов MSDN для GotDotNet, ища XmlNodeWriter.

0 голосов
/ 05 сентября 2008

Одним из решений является сериализация внутреннего объекта в строку, а затем загрузка строки в 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, упомянутый в нескольких блогах!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...