views:

6755

answers:

2

Here's a quick question I've been banging my head against today.

I'm trying to convert a .Net dataset into an XML stream, transform it with an xsl file in memory, then output the result to a new XML file.

Here's the current solution:

        string transformXML = @"pathToXslDocument";

        XmlDocument originalXml = new XmlDocument();

        XmlDocument transformedXml = new XmlDocument();

        XslCompiledTransform transformer = new XslCompiledTransform();

        DataSet ds = new DataSet();

        string filepath;

        originalXml.LoadXml(ds.GetXml()); //data loaded prior

        StringBuilder sb = new StringBuilder();

        XmlWriter writer = XmlWriter.Create(sb);

        transformer.Load(transformXML);

        transformer.Transform(originalXml, writer); //no need to select the node

        transformedXml.LoadXml(sb.ToString());

        transformedXml.Save(filepath);

        writer.Close();

Here's the original code:

BufferedStream stream = new BufferedStream(new MemoryStream());

DataSet ds = new DataSet();

da.Fill(ds);

ds.WriteXml(stream);

StreamReader sr = new StreamReader(stream, true);

stream.Position = 0; //I'm not certain if this is necessary, but for the StreamReader to read the text the position must be reset.

XmlReader reader = XmlReader.Create(sr, null);  //Problem is created here, the XmlReader is created with none of the data from the StreamReader

XslCompiledTransform transformer = new XslCompiledTransform();

transformer.Load(@"<path to xsl file>");

transformer.Transform(reader, null, writer); //Exception is thrown here, though the problem originates from the XmlReader.Create(sr, null)

For some reason in the transformer.Transform method, the reader has no root node, in fact the reader isn't reading anything from the StreamReader.

My questions is what is wrong with this code? Secondarily, is there a better way to convert/transform/store a dataset into XML?

Edit: Both answers were helpful and technically aku's was closer. However I am leaning towards a solution that more closely resembles Longhorn's after trying both solutions.

+2  A: 

I'm not sure but it seems that you didn't reset position in stream before passing it to XmlReader. Try to seek at the beginning of your stream before trying to read from it. Also it may be necessary to close\flush stream after you wrote some data to it.

EDIT:

Just tried following code and it worked perfectly:

    BufferedStream stream = new BufferedStream(new MemoryStream());
    stream.Write(Encoding.ASCII.GetBytes("<xml>foo</xml>"), 0, "<xml>foo</xml>".Length);
    stream.Seek(0, SeekOrigin.Begin);
    StreamReader sr = new StreamReader(stream);
    XmlReader reader = XmlReader.Create(sr);
    while (reader.Read())
    {
         Console.WriteLine(reader.Value);
    }
    stream.Close();
aku
aku, please, please, use `using(...) { ... }` blocks for `IDisposable`s so people won't copy-paste your code and learn bad style from it :( If you want to keep it is as short as possible for small answer size mention somewhere that in real code they SHOULD use `using`s.
IgorK
I don't think it's necessary for short code snippets. For example most of MSDN code samples don't demonstrate good practices. People should think with their head and not blindly copy-paste somebody's code. Also additional braces make code less readable on a web page.
aku
+2  A: 

You must select the root node. This doesn't use Datasets, but I use this function everyday and it works great.

System.Xml.XmlDocument orgDoc = new System.Xml.XmlDocument();
orgDoc.LoadXml(orgXML);

// MUST SELECT THE ROOT NODE
XmlNode transNode = orgDoc.SelectSingleNode("/");
System.Text.StringBuilder sb = new System.Text.StringBuilder();
XmlWriter writer = XmlWriter.Create(sb);

System.IO.StringReader stream = new System.IO.StringReader(transformXML);
XmlReader reader = XmlReader.Create(stream);

System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
trans.Load(reader);
trans.Transform(transNode, writer);

XmlDocument doc = new XmlDocument();
doc.LoadXml(sb.ToString());

return doc;
David Basarab