Форматирование XML, созданного DataContractSerializer - PullRequest
54 голосов
/ 11 апреля 2009

Есть ли простой способ заставить DataContractSerializer выплюнуть отформатированный XML, а не одну длинную строку? Я не хочу менять теги или содержимое каким-либо образом, просто добавьте разрывы строк и отступы, чтобы сделать XML более читабельным?

<tagA>
   <tagB>This is</tagB>   
   <tagC>Much</tagC>
   <tagD>
      <tagE>easier to read</tagE>
   </tagD>
</tagA>


<tagA><tagB>This is</tagB><tagC>Much</tagC><tagD><tagE>harder to read</tagE></tagD></tagA>

Ответы [ 5 ]

86 голосов
/ 11 апреля 2009

Как говорит Бендевей, XmlWriterSettings - это то, что вам нужно - например, что-то вроде

var ds = new DataContractSerializer(typeof(Foo));

var settings = new XmlWriterSettings { Indent = true };

using (var w = XmlWriter.Create("fooOutput.xml", settings))
    ds.WriteObject(w, someFoos);
19 голосов
/ 11 апреля 2009

Взгляните на Indent свойство XmlWriterSettings

Обновление: Вот хорошая ссылка из MSDN на Как: указать формат вывода на XmlWriter

Дополнительно, вот пример:

class Program
{
    static void Main(string[] args)
    {
        var Mark = new Person()
        {
            Name = "Mark",
            Email = "mark@example.com"
        };

        var serializer = new DataContractSerializer(typeof(Person));

        var settings = new XmlWriterSettings()
        {
            Indent = true,
            IndentChars = "\t"
        };

        using (var writer = XmlWriter.Create(Console.Out, settings))
        {
            serializer.WriteObject(writer, Mark);
        }
        Console.ReadLine();
    }
}
public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}
7 голосов
/ 19 февраля 2010

Будьте внимательны при настройке пробелов в документах XML! Корректировка пробелов сделает XML более читабельным для нас, людей, но это может помешать машинному анализу.

В соответствии со стандартом XML , пробелы по умолчанию значительны. Другими словами, что касается XML, пробел - это содержимое .

Если вы подадите свой красиво отформатированный XML в объект XML-документа, вы получите результат, отличный от версии, в которой нет пробелов или разрывов строк. Вы получите дополнительные текстовые узлы, добавленные к отформатированной версии.

Эта статья MSDN о XML White Space содержит несколько примеров, показывающих, насколько сложными могут быть белые пробелы.

Если вы форматируете XML только для потребления человеком, это не имеет значения. Но если вы попытаетесь обойти ваш отформатированный документ, вы можете столкнуться с проблемами.

Поскольку одним из основных преимуществ использования DataContractSerializer является возможность сериализации объектов и десериализации XML плавно , обычно лучше оставить уродливый вывод в одиночку.

Обычно я вставляю вывод в NotePad ++ и запускаю над ним макрос XML-кода, когда хочу прочитать его в целях отладки.

2 голосов
/ 16 ноября 2009
    public static string SerializeEntity<T>(T source)
    {
        using (MemoryStream ms = new MemoryStream())
        {

                NetDataContractSerializer serializer = new NetDataContractSerializer();
                serializer.Serialize(ms, source);
                return System.Text.Encoding.ASCII.GetString(ms.ToArray());

        }
    }

    public static T DeSerializeEntity<T>(string xml)
    {
        using (MemoryStream ms = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(xml)))
        {
                NetDataContractSerializer serializer = new NetDataContractSerializer();
                return (T)serializer.Deserialize(ms);
        }
    }
0 голосов
/ 22 февраля 2013

на основе других примеров, опубликованных здесь, которые используют XmlWriter, вот версия (от http://ClipFlair.codeplex.com), которая работает с потоками (в частности, с библиотекой Ionic.Zip), а также показывает, как работает код, когда вы этого не делаете применить форматирование (используя условную компиляцию - просто закомментируйте #define, чтобы он записывал неформатированный XML)

#define WRITE_FORMATTED_XML

using System.Xml;

namespace ClipFlair.Windows
{

  public partial class BaseWindow : FloatingWindow
  {

    //...

    #if WRITE_FORMATTED_XML
    private static XmlWriterSettings XML_WRITER_SETTINGS = new XmlWriterSettings() { Indent=true, IndentChars="  "};
    #endif

    //...

    public virtual void SaveOptions(ZipFile zip, string zipFolder = "") //THIS IS THE CORE SAVING LOGIC
    {
      if (SavingOptions != null) SavingOptions(this, null); //notify any listeners

      View.Busy = true;
      try
      {
        ZipEntry optionsXML = zip.AddEntry(zipFolder + "/" + View.GetType().FullName + ".options.xml",
          new WriteDelegate((entryName, stream) =>
          {
            DataContractSerializer serializer = new DataContractSerializer(View.GetType()); //assuming current View isn't null
            #if WRITE_FORMATTED_XML
            using (XmlWriter writer = XmlWriter.Create(stream, XML_WRITER_SETTINGS))
              serializer.WriteObject(writer, View);
            #else
            serializer.WriteObject(stream, View);
            #endif
          }));
      }
      catch (Exception e)
      {
        MessageBox.Show("ClipFlair options save failed: " + e.Message); //TODO: find the parent window
      }
      finally
      {
        View.Busy = false; //in any case (error or not) clear the Busy flag
      }

      if (SavedOptions != null) SavedOptions(this, null); //notify any listeners
    }

    //...

  }

}
...