Как создать XmlNode из вызова XmlSerializer.Serialize?
Я использую библиотеку классов, которая представляет некоторую конфигурацию в .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
?
Спасибо,
Кевин
btw-- Похоже, что класс XmlNodeWriter
, написанный Крисом Ловеттом, был доступен в одно время от Microsoft, но теперь ссылки были разбиты. Кто-нибудь знает об альтернативном месте, чтобы получить этот класс?
Ответы
Ответ 1
Итак, вам нужно, чтобы ваш класс содержал пользовательскую конфигурационную информацию, затем сериализовал этот класс в XML, а затем превратил этот сериализованный XML в XML node: это правильно?
Не могли бы вы просто взять строку, созданную 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> ", который имеет в нем свою сериализованную пользовательскую конфигурацию.
Это вообще то, что вы ищете?
Ответ 2
Это заняло немного работы, но маршрут 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);
Ответ 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. В противном случае вы могли бы написать MS, используя эту форму, которую они имеют в новой замене библиотеки кода MSDN для GotDotNet, которая ищет XmlNodeWriter.