Сериализация в XML-фрагмент, а не XML-документ - PullRequest
11 голосов
/ 04 мая 2010

Как сериализовать XML-сериализуемый объект в фрагмент XML (без объявления XML и ссылок на пространство имен в корневом элементе)?

Ответы [ 3 ]

19 голосов
/ 05 мая 2010

Вот хакерский способ сделать это без загрузки всей выходной строки в XmlDocument:

using System;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public class Example
{
    public String Name { get; set; }

    static void Main()
    {
        Example example = new Example { Name = "Foo" };

        XmlSerializer serializer = new XmlSerializer(typeof(Example));

        XmlSerializerNamespaces emptyNamespace = new XmlSerializerNamespaces();
        emptyNamespace.Add(String.Empty, String.Empty);

        StringBuilder output = new StringBuilder();

        XmlWriter writer = XmlWriter.Create(output,
            new XmlWriterSettings { OmitXmlDeclaration = true });
        serializer.Serialize(writer, example, emptyNamespace);

        Console.WriteLine(output.ToString());
    }
}
1 голос
/ 04 мая 2010

Вы должны иметь возможность просто сериализовать, как обычно, и затем использовать свойство Root из полученного документа.

Сначала вам может потребоваться очистить атрибуты элемента.

0 голосов
/ 15 декабря 2011

Кстати, это круто. Я реализовал этот код, чтобы упростить работу с фрагментами XML в виде классов, а затем вы можете просто заменить узел, когда закончите. Это делает переход между кодом и XML очень простым.

Сначала создайте несколько методов расширения.

public static class SerializableFragmentExtensions
{
    public static XElement ToElement(this ISerializableFragment iSerializableFragment)
    {
        var serializer = new XmlSerializer(iSerializableFragment.GetType());
        var emptyNamespace = new XmlSerializerNamespaces();
        emptyNamespace.Add(String.Empty, String.Empty);

        var output = new StringBuilder();

        var writer = XmlWriter.Create(output,
            new XmlWriterSettings { OmitXmlDeclaration = true });
        serializer.Serialize(writer, iSerializableFragment, emptyNamespace);
        return XElement.Parse(output.ToString(), LoadOptions.None);
    }
    public static T ToObject<T>(this XElement xElement)
    {
        var serializer = new XmlSerializer(typeof (T));
        var reader = xElement.CreateReader();
        var obj = (T) serializer.Deserialize(reader);
        return obj;
    }
}

Далее Реализация необходимого интерфейса (маркерный интерфейс - я знаю, что вы не должны, но я думаю, что это идеальная причина для этого.)

public interface ISerializableFragment
{
}

Теперь все, что вам нужно сделать, это украсить любой класс Serializable, который вы хотите преобразовать во фрагмент XElement, с помощью интерфейса.

[Serializable]
public class SomeSerializableClass : ISerializableFragment
{
    [XmlAttribute]
    public string SomeData { get; set; }
}

Наконец, проверьте код.

    static void Main(string[] args)
    {
        var someSerializableClassObj = new SomeSerializableClass() {SomeData = "Testing"};
        var element = someSerializableClass.ToElement();
        var backToSomeSerializableClassObj = element.ToObject<SomeSerializableClass>();
    }

Еще раз спасибо за этот удивительно полезный код.

...