views:

219

answers:

4

I have a stream object, and I want to create and output xml using some kind of xml stream, based on data in my input stream. I haven't done much work with streams, so I am trying to learn how to do this as efficiently as possible. The idea is that I do not want to load the entire input stream in memory, then create the entire output stream in memory because at some point you end up with at least double the size of the input stream taking up memory.

There must be ways so that as data is read in the input stream, the xml stream is built and the data read from the input stream is discarded. Additionally, I would like to architect it so that the xml stream isn't built completely then passed out, but instead the xml stream can be read as it is being built. Does anyone have some code samples, or good resources for learning about this?

+2  A: 

XmlTextReader is used if you need to access the XML as raw data without the overhead of an in memory Document Object Model (DOM)

XmlTextReader provides a faster mechanism for reading XML. The following code loads XmlTextReader from a stream.

using (XmlTextReader reader= new XmlTextReader (stream)) {

while (reader.Read()) 
{
    switch (reader.NodeType) 
    {
        case XmlNodeType.Element: // The node is an Element.
            Console.Write("<" + reader.Name);
   Console.WriteLine(">");
            break;
  case XmlNodeType.Text: //Display the text in each element.
            Console.WriteLine (reader.Value);
            break;
  case XmlNodeType. EndElement: //Display end of element.
            Console.Write("</" + reader.Name);
   Console.WriteLine(">");
            break;
    }
}


}
amazedsaint
I'm not sure the input stream is xml. Sounds more like it's other data being converted to xml.
Joel Coehoorn
@Joel, yes. It's from a tcp stream, which gets parsed and xml built up based on that data.
Jeremy
A: 

You can use XmlReader.Create method to create an instace a XmlReaderObject. Use XmlReaderSettings to specify XML Settings(XSD,IgnoreComments,etc.)

        XmlReaderSettings settings = new XmlReaderSettings(){
        settings.IgnoreComments = true;
        using (XmlReader reader = XmlReader.Create("Test.xml",settings)){
            while(reader.Read()){

                // Construct/Evaluate XML Here....
            }
            reader.Close();
        }
    }
Igor Zelaya
+1  A: 

For writing your XML out as a stream, use XmlTextWriter.

You can give it a stream to write to. This will give you what you want (stream output) and give you a lot of flexibility. By passing the stream to use to your code as an argument, you could hook up a memory stream, or a file stream or just about anything without the XML formatting code needing to know. The XmlTextWriter will periodically flush the data (so it wont stick around unless nothing reads it from the stream), just remember to do a final flush/close at the end.

Streams are also how you will handle input. As you process that input and can decide on what XML elements to write, use the XmlTextWriter to write them and it will take care of streaming that data out to whoever will be reading it. So you end up with a loop (or loops) that is reading a bit, doing some processing, then writing to the XmlTextWriter all at once.

JasonMArcher
Is there a forward only stream available I can use? Memory stream is seekable, so it will continue to fill memory even as I read it. Is there something that will remove data from the stream as I read it?
Jeremy
You could write to a file with FileStream and FileMode.Append and FileAccess.Write. Or maybe System.IO.Pipes.PipeStream (.NET 3.5) will work for you. I haven't used .NET pipes before so I can't tell you from experience. But I have used Java streams.
JasonMArcher
A: 

If you are using .net 3.5, You could use XLINQ. This is the example from http://blogs.msdn.com/wriju/archive/2007/02/20/xlinq-create-xml-from-object-using-linq.aspx

If you do a google on "xlinq create" You will find many examples (you would probably be most interested in the RSS examples, I am thinking.

var objCust = new[]
{
 new {CustID = 2, CustName = "Sumitra", Phone = "123-123-1236"},
 new {CustID = 3, CustName = "Wriju", Phone = "123-123-1235"},
 new {CustID = 4, CustName = "Writam", Phone = "123-123-1234"},
 new {CustID = 1, CustName = "Debajyoti", Phone = "123-123-1237"}   
};
XElement _customers = new XElement("customers",
                        from c in objCust
                        orderby c.CustID //descending 
                        select new XElement("customer",
                            new XElement("name", c.CustName),
                            new XAttribute("ID", c.CustID),
                            new XElement("phone", c.Phone)
                                            )
                                    );
Console.WriteLine(_customers);

output will look like this:

<customers>
  <customer ID="1">
    <name>Debajyoti</name>
    <phone>123-123-1237</phone>
  </customer>
  <customer ID="2">
    <name>Sumitra</name>
    <phone>123-123-1236</phone>
  </customer>
  <customer ID="3">
    <name>Wriju</name>
    <phone>123-123-1235</phone>
  </customer>
  <customer ID="4">
    <name>Writam</name>
    <phone>123-123-1234</phone>
  </customer>
</customers>
Muad'Dib