Web EricSavage  -  05 Jun 2009 02:37 pm

Active Reports rapid Xml processing options

Active Reports provides the XMLDataSource option for sourcing your data from xml.  My knowledge of all its ins and outs is not substantial, but I ran into two significant problems in a recent project which led me towards an alternative, innovative approach.

The first problem is that an xml document does not guarantee a structure like a database does.  Xml’s flexibility in the layout of elements is beautiful on one hand but hard to fit into a report that expects a fixed structure.

The second problem in my case was the use of sub-reports to cover for different structures in the xml document.  I won’t get fully into the detail, but where an element holds recurring sub-items, you can use sub-reports to list all the items.  The trouble is that a significant number of sub-reports kill your report generation performance.  I had a particular problem where my first report would take 15 seconds to generate on the server, and then degrade by another 5 seconds every time I ran it again.  This is of course totally unacceptable for a frequently used report.

Here then was my innovation … combine Active Reports and XSLT.  Active Reports provides the RichTextBox, which has an Html property to which you can assign the Html you generate from your XSLT.

Now there are a few pros and cons worth mentioning here.  Firstly, using reports as the output of your html provides pagination, which is a lot harder to pull off with pure XSLT and html pages.  As a con, XSLT is obviously not the most friendly computer language you’ve ever used and certainly not as easy as using a visual report designer.  What can be said though is that it is technically testable, or in other words, you can write a set of unit tests to ensure that it does what it’s meant to, which in my opinion is rather hard with Active Reports.

The other concern which needs to be mentioned is that the RichTextBox Html feature is something of a work in progress at the Active Reports lab.  I was originally using the version 3 build 5.0.0.117, which had a number of deficiencies in the html formatting, including no underlining and bold.  I upgraded to build 5.2.1236.2 (released May 2009), which fixed a number of issues, but still inserts an extra new line between tables.

Where the previous report was taking anything from 15 to 90 seconds to run, the newer version ran in 3 to 4 seconds consistently, a massive improvement.  For now I’m willing to suffer the trade-offs in order to get the rapid report generation.

Here then is the general code to generate the Html.  You’ll obviously need to adapt it for your own structure.  In this case the XML I wanted to transform was actually stored in the XMLDataSource, whereas you might source your xml from elsewhere.  You’ll notice that the html needs to be generated for each node or each instance of the detail section.

private void detail_Format(object sender, EventArgs e)
{
    XMLDataSource dataSource = (XMLDataSource)this.DataSource;

    if (_recordCounter >= dataSource.NodeList.Count) return;
    XmlNode resultRootNode =
       dataSource.NodeList[_recordCounter].ParentNode;

    string htmlOutput = GenerateResultsHtml(
       resultRootNode.OuterXml, _xslFilePath);
    const string xmlHeader =
       @"<?xml version=""1.0"" encoding=""utf-8""?>";
    resultsTextBox.Html = htmlOutput.Replace(xmlHeader, "");

    _recordCounter++;
}
public static string GenerateResultsHtml(string xml,
    string xslFilePath)
{
    XsltSettings settings = new XsltSettings();
    settings.EnableDocumentFunction = true;
    settings.EnableScript = true;

    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(xslFilePath, settings, null);

    XmlReader xmlReader = XmlReader.Create(new StringReader(xml));
    StringBuilder stringBuilder = new StringBuilder();
    XmlWriter xmlWriter = XmlWriter.Create(
        stringBuilder, transform.OutputSettings);

    if (xmlWriter != null)
    {
        transform.Transform(xmlReader, xmlWriter);
        xmlWriter.Close();
    }
    xmlReader.Close();
    return stringBuilder.ToString();
}

As one last admission, the XSLT was already available for me to use.  Be warned that the transform language while very powerful is a little bit thorny.  At any rate, if you’re experiencing the kinds of problems I was, this may be a viable solution.

One Response to “Active Reports rapid Xml processing options”

  1. on 01 Jul 2009 at 7:20 am 1.Active Reports rapid Xml processing options | XML Developer said …

    [...] Read the original: Active Reports rapid Xml processing options [...]

Trackback This Post | Subscribe to the comments through RSS Feed

Leave a Reply