4

I need to set the OmitXmlDeclaration property of the XmlWriterSettings for a XmlWriter to false to not have XML declarations created. The issue is that I have created the XmlWriter from a call of a XPathNavigator.AppendChild() method. Code below:

    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;
    }

Any idea how to serialize the List and not have XML declarations?

Chris Woodruff
  • 1,323
  • 3
  • 14
  • 30
  • In my answer, I assumed you are trying to add the serialized xml to an existing document. Is that the case? Also, do you need to omit the xml declaration from resultString? – rsbarro Feb 11 '12 at 14:55
  • rsbarro -- you are correct. I am looking at getting a xml serialization of a collection of entities and then adding it to a combined document with several serializations. – Chris Woodruff Feb 12 '12 at 14:33

2 Answers2

3

Try this approach (switched to var for readability):

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();
    }
}

Rather than using nav.AppendChild() to create the XmlWriter, you can create the XmlWriter separately and then just use nav.AppendChild(string) to write the XML into xmlDoc. When you create the XmlWriter yourself, you can omit the XML declaration. Also, when you serialize, you'll probably want to omit the xmlns:xsi and xmlns:xsd namespaces using the XmlSerializerNamespaces class.

rsbarro
  • 27,021
  • 9
  • 71
  • 75
  • -1: Please replace `new XmlTextWriter()` with `XmlWriter.Create()` and I'll upvote. – John Saunders Feb 11 '12 at 02:08
  • @JohnSaunders Updated, but I was just copying the code from the OP. I don't think that part of code is relevant to the question he is asking. =] I'm pretty sure he's trying to figure out how to insert the serialized xml into an existing xml document (since there are far simpler ways to write the `GetEntityXml` method, as the other answer clearly points out). – rsbarro Feb 11 '12 at 02:18
  • +1 Readers copy and paste the code we post, even if we intend it as an example of something else. BTW, I'm letting you get away with no `using` blocks because I'm in a good mood. – John Saunders Feb 11 '12 at 03:19
  • I hear you, will update that as well. I was trying to not get too far from the original just to illustrate the changes I was suggesting, but I see your point. – rsbarro Feb 11 '12 at 03:30
3

I’m not getting the XML declaration when I execute your code. Serializing a List<int> gives me:

<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>

Note that the “XML declaration” that OmitXmlDeclaration refers to is typically something similar to:

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

If you’re instead referring to the xmlns parts, then those are called “XML namespace declarations”, and may be eliminated by initializing an XmlSerializerNamespaces instance with a default empty namespace, and passing it to your Serialize method:

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);

The below is a shortened implementation which achieves the same result as your code:

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();
}
Douglas
  • 53,759
  • 13
  • 140
  • 188
  • I think the sample code is a little misleading. I assumed that he's trying to add children to an already existing XML document, in which case the `XmlSerializer` does write out the xml declaration and cause his sample code to crash. Take the sample code and add the following after the xmlDoc is declared and you'll see what I mean: `xmlDoc.LoadXml(""); var nav = xmlDoc.DocumentElement.CreateNavigator();` – rsbarro Feb 10 '12 at 19:32
  • Yes, that could be the case. The creation of the `XPathNavigator` seemed too pointless, given that he already knew he could initialize `XmlWriter` directly. – Douglas Feb 10 '12 at 19:58