Search code examples
c#xmlcompressionxmlreader

Compress XML during XMLReader.Read()


I have a method which loops through an XML document using an XMLReader (validating at the same time) extracting specific pieces of information. I also need to compress the entire XML document in preparation for storing it in a database. The code I have to do this is below. Is this (passing the entire XmlReader to StreamWriter.Write()) the appropriate / most efficient way to achieve this? I didn't see a clear way to use the while(validatingReader.Read()) loop to achieve the same result.

XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add("schemaNamespace", "schemaLocation");

XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.ValidationType = ValidationType.Schema;
readerSettings.Schemas.Add(schemaSet);
readerSettings.ValidationEventHandler 
                 += new ValidationEventHandler(XMLValidationError);

using (XmlReader documentReader = requestXML.CreateNavigator().ReadSubtree())
{
    using (XmlReader validatingReader = 
            XmlReader.Create(documentReader, readerSettings))
    {
        using (MemoryStream output = new MemoryStream())
        {
            using (DeflateStream gzip = 
                    new DeflateStream(output, CompressionMode.Compress))
            {
                using (StreamWriter writer = 
                        new StreamWriter(gzip, System.Text.Encoding.UTF8))
                {
                    writer.Write(validatingReader);
                    this.compressedXMLRequest 
                                    = Encoding.UTF8.GetString(output.ToArray());
                }
            }
        }
        while (validatingReader.Read())
        {
            // extract specific element contents

        }
    }
}

Solution

  • For future reference:

    The code in the Question does not work properly. Passing an XmlReader to a StreamWriter doesn't work as expected. In the end I didn't end up combining compression with validation in this way so I don't exactly have "correct" code to show for this but didn't want to leave the question dangling.