Как установить XmlWriter.XmlWriterSettings при создании из XPathNavigator.AppendChild ()? - PullRequest
3 голосов
/ 10 февраля 2012

Мне нужно установить для свойства OmitXmlDeclaration XmlWriterSettings для XmlWriter значение false, чтобы не создавать декларации XML.Проблема в том, что я создал XmlWriter из вызова метода XPathNavigator.AppendChild ().Код ниже:

    public String GetEntityXml<T>(List<T> entities)
    {
        XmlDocument xmlDoc = new XmlDocument();
        XPathNavigator nav = xmlDoc.CreateNavigator();

        using (XmlWriter writer = nav.AppendChild())
        {

            XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
            ser.Serialize(writer, entities);
        }

        StringWriter stringWriter = new StringWriter();
        XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);

        xmlDoc.WriteTo(xmlTextWriter);

        string resultString = stringWriter.ToString();

        stringWriter.Close();
        xmlTextWriter.Close();

        return resultString;
    }

Есть идеи, как сериализовать список и не иметь объявлений XML?

Ответы [ 2 ]

3 голосов
/ 10 февраля 2012

Я не получаю объявление XML, когда выполняю ваш код. Сериализация List<int> дает мне:

<Int32_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <int>5</int>
  <int>7</int>
  <int>2</int>
</Int32_LIST>

Обратите внимание, что «декларация XML», на которую ссылается OmitXmlDeclaration, обычно похожа на:

<?xml version="1.0" encoding="UTF-8" ?>

Если вместо этого вы ссылаетесь на части xmlns, то они называются «XML пространство имен объявления» и могут быть устранены путем инициализации экземпляра XmlSerializerNamespaces пустым пространством имен по умолчанию, и передавая его вашему Serialize методу:

XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
var namespaces = new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") });
ser.Serialize(writer, entities, namespaces);

Ниже приведена сокращенная реализация, которая достигает того же результата, что и ваш код:

public String GetEntityXml<T>(List<T> entities)
{
    var sb = new StringBuilder();
    var settings = new XmlWriterSettings { OmitXmlDeclaration = true };
    using (XmlWriter writer = XmlWriter.Create(sb, settings))
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
        var namespaces = new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") });
        ser.Serialize(writer, entities, namespaces);
    }
    return sb.ToString();
}
2 голосов
/ 10 февраля 2012

Попробуйте этот подход (переключен на var для удобства чтения):

public String GetEntityXml<T>(List<T> entities)
{
    var xmlDoc = new XmlDocument();
    var nav = xmlDoc.CreateNavigator();
    using (var sw = new StringWriter())
    {
        //Create an XmlWriter that will omit xml declarations
        var s = new XmlWriterSettings{ OmitXmlDeclaration = true };
        using (var xmlWriter = XmlWriter.Create(sw, s))
        {
            //Use the following to serialize without namespaces
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            var ser = new XmlSerializer(typeof(List<T>),
                          new XmlRootAttribute(typeof(T).Name + "_LIST"));
            ser.Serialize(xmlWriter, entities, ns);
        }

        //Pass xml string to nav.AppendChild()
        nav.AppendChild(sw.ToString());
    }

    using (var stringWriter = new StringWriter())
    {
        using (var xmlTextWriter = XmlWriter.Create(stringWriter))
        {
            xmlDoc.WriteTo(xmlTextWriter);
        }
        return stringWriter.ToString();
    }
}

Вместо того, чтобы использовать nav.AppendChild() для создания XmlWriter, вы можете создать XmlWriter отдельно, а затем просто использовать nav.AppendChild(string) для записи XML в xmlDoc. Когда вы создаете XmlWriter самостоятельно, вы можете опустить декларацию XML. Кроме того, при сериализации вы, возможно, захотите пропустить пространства имен xmlns:xsi и xmlns:xsd, используя класс XmlSerializerNamespaces.

...