Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Part 5. Assigning Dynamic Data

Not Rated Yet

This article is the last of a 5 part course in complex data-binding with namespaces, making choices, dynamic parameters and dynamic data.

 

Course Contents

 

Building on our data-binding articles, the final piece to the puzzle is how to dynamically alter the output at runtime. With scryber we can specify parameter values and even the loaded data quickly and easily.

 

Article Contents

 

Dynamic Parameters

 

In our previous article DB Part 4 Transform Parameters we created an XMLDataSource with 2 XSLT Arguments that we used to alter the flow and style of content in the generated PDF. We can now alter the output using these parameters in the document template.
Let's include the totals, add an item parameter for target, and alter the break-even value

    <data:XMLDataSource id="MyStyledSalesData" source-path="./Data/Sales.xml">
      <Transform path="./Data/SalesToTotalsWithRange.xslt" >
        <data:XsltItemArgument item-name="break-even" name="break-even" default-value="25000" />
        <data:XsltItemArgument item-name="target" name="target" default-value="30000" />
        <data:XsltArgument name="show-totals" value="Yes"/>
      </Transform>
      <Namespaces>
        <data:Xmlns prefix="s" namespace="http://sample.xml.com/sales"/>
        <data:Xmlns prefix="e" namespace="http://sample.xml.com/sales/envelope"/>
      </Namespaces>
    </data:XMLDataSource>

 


 

Dynamic parameters in code

 

So we know the parameters work when we alter the values and give us the ability to tailor our report as required - As a further advantage we have our XSLTItemArguments passed to the XSLT transformation. These enable us to dynamically adjust the output at run time, not just design time. Once the document has been created from the template we can set the new values on the item collection. This will be picked up when the components are data-bound, and appropriate decisions made.

 

    doc = Scryber.Components.PDFDocument.ParseDocument(path);
    doc.Items["break-even"] = 30000;
    doc.Items["target"] = 35000;
    doc.ProcessDocument(outputstream, true);

 


 

We can see these values have been picked up by the transformation and used in the template.

NOTE: The XMLDataSource supports data caching. When this value is set, the raw datasource and any transformer are loaded and cached, but the result is not cached. It is calculated and returned dynamically.
As such - if you make changes to a data source, or an XSLT file, then the they may not immediately be used. But changes to data source parameters will always be up to date, at the expense of transforming the data every time.
If this is not required you can implement your own transformation cache this.

 

Dynamic data at Runtime

 

We now have our parameters dynamically assigned values from within code, but what happens if we want our actual data to be dynamic. Load the Sales data from another source and inject it dynamically into the Document

Our first option is to get hold of the XMLDataSource component. And then set the data value there from some method that will return a System.XML.XPath.XPathNavigator instance.

 

    doc = Scryber.Components.PDFDocument.ParseDocument(path);
    doc.Items["break-even"] = 30000;
    doc.Items["target"] = 35000;
	
    Scryber.Data.PDFXMLDataSource src = ((Scryber.Data.PDFXMLDataSource)doc.FindAComponentById("MyStyledSalesData"));
    if(null != src)
        src.XmlData = GetMyXMLNavData();
	
    doc.ProcessDocument(outputstream, true);

 

We can now modify the data at runtime whenever we require

 

Dynamic data at Runtime - New and Improved

 

The above example works perfectly, but does tie the code to the runtime requirement that the MyStyledSalesData component being present. No compile time error will be generated.

As of version 0.8.9.0 we can take advantage of the Item and Query String Binding capabilities to decouple the structure from the code and update our XMLDataSource to actually retrieve it's data dynamically from the Document.Items collection.

 

    <data:XMLDataSource id="MyStyledSalesData" xml-node-data="{item:sales-data}">
      <Transform path="./Data/SalesToTotalsWithRange.xslt" >
        <data:XsltItemArgument item-name="break-even" name="break-even" default-value="25000" />
        <data:XsltItemArgument item-name="target" name="target" default-value="30000" />
        <data:XsltArgument name="show-totals" value="Yes"/>
      </Transform>
      <Namespaces>
        <data:Xmlns prefix="s" namespace="http://sample.xml.com/sales"/>
        <data:Xmlns prefix="e" namespace="http://sample.xml.com/sales/envelope"/>
      </Namespaces>
    </data:XMLDataSource>

 

    doc = Scryber.Components.PDFDocument.ParseDocument(path);
    doc.Items["break-even"] = 30000;
    doc.Items["target"] = 35000;
    doc.Items["sales-data"] = GetMyXMLNavData();
	
    doc.ProcessDocument(outputstream, true);

 

This gives us the same output (for the same data) but is more loosely coupled. One requirement for the item binding here is that the XMLDataSource must be databound before any component tries to lookup the data in this datasource - e.g A data:ForEach component, so as data binding follows the structure of the template, the datasouce must be above / before the ForEach component.

 

See Also.

 



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  No Ratings Yet   
Number of Ratings : 0
  Comments
Add Comment
No Comments Yet