7

Am trying to serialize a class, writing to an XML file as multiple fragments, i.e, write each object of the class as an individual fragment, without the XML header/root. Below is a sample code:

[Serializable]
public class Test
{
    public int X { get; set; }
    public String Y { get; set; }
    public String[] Z { get; set; }

    public Test()
    {
    }

    public Test(int x, String y, String[] z)
    {
        X = x;
        Y = y;
        Z = z;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Test t1 = new Test(1, "t1", new[] { "a", "b" });
        Test t2 = new Test(2, "t2", new[] { "c", "d", "e" });

        XmlSerializer serializer = new XmlSerializer(typeof(Test));
        //using (StreamWriter writer = new StreamWriter(@"f:\test\test.xml"))
        {
            XmlWriter xmlWriter = XmlWriter.Create(@"f:\test\test.xml",
                                                   new XmlWriterSettings()
                                                       {ConformanceLevel = ConformanceLevel.Fragment,
                                                        OmitXmlDeclaration = true,
                                                        Indent = true});
            serializer.Serialize(xmlWriter, t1);
            serializer.Serialize(xmlWriter, t2);
            xmlWriter.Close();
        }
    }
}

In the first call to serialize, I get the exception:

WriteStartDocument cannot be called on writers created with ConformanceLevel.Fragment

What am I missing here?

sppc42
  • 2,994
  • 2
  • 31
  • 49

1 Answers1

17

there is a workaround to this problem. When the xml writer has been used before you use the serializer, then the header won't be written. The following does work, but will add an empty comment tag on the first line of the xml file

improved code as suggested by oleksa

static void Main(string[] args)
    {
        Test t1 = new Test(1, "t1", new[] { "a", "b" });
        Test t2 = new Test(2, "t2", new[] { "c", "d", "e" });

        XmlSerializer serializer = new XmlSerializer(typeof(Test));
        //using (StreamWriter writer = new StreamWriter(@"f:\test\test.xml"))
        {
            XmlWriter xmlWriter = XmlWriter.Create(@"test.xml",
                                                   new XmlWriterSettings()
                                                   {
                                                       ConformanceLevel = ConformanceLevel.Fragment,
                                                       OmitXmlDeclaration = false,
                                                       Indent = true,
                                                       NamespaceHandling = NamespaceHandling.OmitDuplicates
                                                   });
            xmlWriter.WriteWhitespace("");
            serializer.Serialize(xmlWriter, t1);
            serializer.Serialize(xmlWriter, t2);
            xmlWriter.Close();
        }
    }
Wim Reymen
  • 190
  • 2
  • 4
  • Great, that just works fine. I don't mind an empty comment in the file – sppc42 Sep 27 '13 at 13:30
  • Note that the [`NamespaceHandling`](http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.namespacehandling.aspx) property only exists in .NET 4.0 and above. – John Saunders Sep 30 '13 at 00:13
  • 4
    It is possible to write nothing with `xmlW.WriteWhitespace("")` – oleksa Apr 22 '14 at 13:03
  • 1
    Empty comments - yuck! empty whitespace as oleksa suggested is better. Tooks me a while to get to a nice serialize with XmlWriter for a fragment. – Andez Oct 18 '14 at 18:07
  • oleksa's solution uniquely better, please write post. – Igor Semin Oct 27 '14 at 13:28
  • Use `xmlWriter.WriteString("")` in order to make this piece of code compatible with Mono due to [this validity check](https://github.com/mono/mono/blob/master/mcs/class/System.XML/System.Xml/XmlTextWriter2.cs#L1060). – Gorka Lerchundi Osa Jan 13 '15 at 12:46