#c# #.net #xml #serialization
#c# #.net #xml #сериализация
Вопрос:
Я сериализую объект с помощью XmlSerializer, указывая атрибуты внутри моего объекта, чтобы давать инструкции XmlSerializer, например:
[XmlType("FooElement")]
public class Foo {
[XmlAttribute("Type")]
public string fooType;
[XmlElement("Name")]
public string Name;
[XmlElement("Bar")]
public Bar BarObject;
}
public class Bar {
[XmlElement("Message")]
public string BarString;
[XmlElement("From")]
public string FromName;
}
Когда объект типа Foo сериализуется, генерируется следующий XML:
<Foo Type="TypeName">
<Name>Name of Foo</Name>
<Bar>
<Message>5:00 Somewhere</Message>
<From>Jane Smith</From>
</Bar>
</Foo>
Я хочу, чтобы все данные в Foo были выровнены до одного уровня, например:
<Foo Type="TypeName">
<Name>Name of Foo</Name>
<Message>5:00 Somewhere</Message>
<From>Jane Smith</From>
</Foo>
Для моих нужд важно, чтобы Foo и Bar оставались отдельными классами. Помимо объединения классов, как бы я мог объединить элементы Foo в один уровень при сериализации в формате XML? Было бы лучше, если бы это можно было сделать с помощью тегов [Property] . Я открыт для переключения моего метода сериализации XML.
Редактировать: я переключился на класс XmlWriter. Это позволит мне писать XML-элементы в иерархии, которую я ищу. Программа, использующая созданный здесь XML, намного проще, чем инструменты C # XML. У более простого анализатора возникли трудности с XML, сгенерированным XmlSerializer.
Ответ №1:
Это должно сделать это
void Main()
{
var foo = new Foo
{
Name = "name",
fooType = "type",
BarObject = new Bar { BarString = "bar"}
};
var s = new XmlSerializer(typeof(Foo));
using (var writer = new StringWriter())
{
s.Serialize(writer, foo);
writer.ToString().Dump();
}
}
public class Foo {
[XmlAttribute("Type")]
public string fooType;
[XmlElement("Name")]
public string Name;
[XmlElement("Message")]
public Bar BarObject;
}
public class Bar {
[XmlText]
public string BarString;
}
Вывод:
<?xml version="1.0" encoding="utf-16"?>
<Foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Type="type">
<Name>name</Name>
<Message>bar</Message>
</Foo>
Комментарии:
1. Это выглядит великолепно. Один вопрос: можно ли масштабировать это так, чтобы, если Bar содержит более одного элемента (сообщение, дату и т. Д.), Каждый элемент в Bar отображался в элементе Foo в XML?
2. @ford, если вы добавите дополнительные свойства / поля в
Bar
класс? Конечно, почему бы и нет. Просто добавьте и пометьте их как[XmlElement]
. В противном случае я не уверен, что вы имеете в виду.3. Спасибо за просьбу о разъяснении. Я отредактировал свой вопрос.
4. @ford я вижу … нет, насколько мне известно, это невозможно. Я спрашиваю, зачем вам это нужно, поскольку сериализованные XML-данные предназначены для представления дерева объектов, которое вы сериализуете. Даже приведенный мной пример является взломом, поскольку
XmlText
сериализуется как узел (текстовый узел), который является дочерним элементом узлаMessage
. Возможно, если бы вы представили свою проблему более высокого уровня, я мог бы придумать обходной путь или убедить вас, что ваше требование недействительно.5. знать это достаточно хорошо. Я рассмотрю это под другим углом и устраню требование сглаживания иерархии. В основном я хотел упростить XML для читателя с другой стороны, и похоже, что этот метод вместо этого усложнит ситуацию.
Ответ №2:
Я не знаю способа сделать это без добавления свойств в Foo, которые сопоставляются с соответствующими свойствами Bar . Например:
[XmlType("FooElement")]
public class Foo {
[XmlAttribute("Type")]
public string fooType;
[XmlElement("Name")]
public string Name;
[XmlIgnore()]
public Bar BarObject;
[XmlElement("Message")]
public string BarMessage
{
get {
return this.Bar.BarString;
}
set {
this.Bar.BarString = value;
}
}
public class Bar {
public string BarString;
}