See the question and my original answer on StackOverflow

The trace data is under cover a standard DataSet. You can't get a hold on it officially, but here is a hack that can do it (it seems to work on .NET 2 to 4):

public static DataSet GetTraceData(Page page)
    if (page == null)
        throw new ArgumentNullException("page");

    return (DataSet)typeof(TraceContext).GetField("_requestData",
           BindingFlags.NonPublic | BindingFlags.Instance).GetValue(page.Trace);

Once you have the DataSet, you can do anything you want with it, save to an XML file (DataSet.WriteXml), a stream, etc.

Of course, since it uses an internal field, it may not be supported in the future.