0

This is what I'm trying to do. I'm sure the solution is simple, I just haven't found it yet (and believe me I've been trying).

  • I have an object that I want to use to create XML data. (I'm using an XmlTextWriter to create the elements.)
  • I then want to pass the XML data to another method.
  • This method should take the XML data and uses it as the input for an XSLT transformation to get HTML.

The Transform method works with an XMLReader, so basically I want to first write something with an XmlTextWriter and pass this to an XmlReader.

Of course I could just write to a file and then read the file again, but I thought it would be easier to just handle the data in memory and not actually write it to a file.

The reason why I'm not directly using an HtmlTextWriter is simple: As far as I understand this only works in .NET 4.5 and for various reasons the project needs to stay in 4.0.

There is also the option to pass an XML from another source later on, which is why I'd like to stick with XSLT transformation. Also, this will make changing the layout of the HTML form easier later on, since I would only have to change the XSLT template and not change the actual code.

Anne Schuessler
  • 1,692
  • 13
  • 25
  • HtmlTextWriter is from .Net 1 – AK_ Apr 15 '13 at 09:57
  • Oh, you're right. Strangely enough what I tried with that didn't work until I changed the project properties to .Net 4.5. I'd still like to go with the XSLT transformation since it will allow me to pass in XML from another source and reuse the XSLT template to make sure that there are no redundancies. – Anne Schuessler Apr 15 '13 at 10:00

3 Answers3

1

you could:

StringBuilder sb = new StringBuilder();
var writer = new XmlWriter(sb);

WriteStuff( writer );

writer.Flush();

string s = sb.ToString();

XmlReader reader = new XmlReader(s);

DoStuff(reader);

Not sure what you want to do, or if that's the best way to do it... But you can.


This will also work in a similar way with MemoryStream, Which will probably be more appropriate for a lot of data... just don't forget to Flush...

AK_
  • 7,981
  • 7
  • 46
  • 78
0

Whenever you want to sendan ordered amount of bytes to another "thingy", which needs to interpret the bytes in the same order to which it was sent, it is wise to use a System.IO.Stream class.

Using this class you declare that you don't really care where the bytes are going to, as long as the order remains the same. So both the writer and the reader of the bytes don't care whether the stream of bytes is put in a file, a piece of memory, even a papertape reader, as long as the order isn't changed, and no byte is being added or lost.

In practice: whenever you think you could write them on a file, after which you'd give the filename to someone else, you could also use a stream. Either you, or the object that ordered you to write it to the file, creates the stream with the destination of the stream (memory / papertape / file). The stream is than passed to the other, who can read the stream.

Example: MySpecialObject has some data: MySpecialData. There are classes to serialize and deserialize this special data. These classes are not interested where the data is fysically serialized: patertape? diskette? memory. They only need to know that they can (de)serialize it by writing and reading a stream of bytes. IN that case you use an instance of System.IO.Stream.

(I write the namespaces, to make it easier to find the classes)

class MySerializer
{
    private System.IO.Stream myStream = null;

    public MySerializer(system.IO.Stream stream)
    {
        this.myStream = stream;
    }

    public void Serialize(object data)
    {
        System.Xml.Serialization.XmlSerializer serializer =
            new System.Xml.SerializationXmlSerializer(data.GetType());

    System.XML.XmlWriter writer = System.XML XmlWriter.Create(this.MyStream);

    serializer.Serialize(writer, data);
    }
}

If you look closely, you'll see that the only difference with using a file is the parameter in XMLWriter.Create()

Now the usage of this in mySpecialObject:

public void SerializeMySpecialData()
{
    System.IO.Stream myStream = new System.IO.MemoryStream();
    // in this case: read and write using only memory.
    // if you want to write to something else, for instance a file,
    // create a file stream.
    // or any other subclass from Sytem.IO.Stream. The serializer won't notice
    // where it is actually stored.
    MySerializer mySerializer = new MySerializer(myStream);
    mySerializer.Serialize(mySpecialData);
    myStream.Flush();
    myStream.Close();
    myStream.Dispose(); // this function will probably also flush and close
}

Reading XML from a stream is similar as reading XML from a file:

public object Deserialize(System.Type expectedDataType)
{
    object data = null;
    System.Xml.Serialization.XmlSerializer deserializer =
        new System.Xml.SerializationXmlSerializer(expectedDataType);

    System.XML.XmlReader reader = System.XML XmlReader.Create(this.MyStream);

    deserializer.Deserialize(reader, data);
    return data;
}

Once again: the advantage is that the caller decides where the data actually is stored. If the data is stored on a different type of media the serialization classes won't see the difference, and thus won't have to change.

You could also decide to hide to the user of the serialization classes where the data is stored. In that case the constructor of the serialization class creates the stream. This approach would be useful if you want all data to be serialized all on the same medium.

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116
  • Looks like a typo here: System.Xml.Serialization.XmlSerializer serializer = new System.Xml.**Serialization.XmlSerializer**(data.GetType()); – JohnnyBizzle Nov 17 '14 at 16:20
0

To save on xml parsing, I would suggest to write all data into XmlDocument using XmlWriter, and then create XmlReader from it:

//create xml data
XmlDocument doc = new XmlDocument(); 
using (XmlWriter writer = doc.CreateNavigator().AppendChild()) 
{
   CreateXmlData(writer);  
}

//pass xml data to transform as reader
using (XmlReader reader = new XmlNodeReader(doc))
{
  Transform(reader);
}
Alexander
  • 4,153
  • 1
  • 24
  • 37