Here is some Xslt used during production. It takes an SPBModel Xml file containing both Input and Output. It assumes the Input has been structured to emulate the Spot-Visit relationship. It then compares observed conditions described in the Visits subsequent to the first to the model's predicted conditions for that date--outputting a table with a row for every former-Visit, now-Frame in the Input dataset.
This Xslt is used to form the Summary Table at the end of the Workflow Example.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
><xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
<!-- // Transform SPBModel Xml to an Html Table Error Report // Input will have Batch and Frames structured // Similarly to Spots and Visits. The first visit frame // to each spot will be modeled into the EngineOutput // elements. This Xslt will compare // subsequent visit frame observation values to // the computed values based on the first frame.--> <!-- // Here are some interesting numbers and relation keys. SpotName GregorianDate OrdinalDay SimulationDay Temperature // Here are the parameters. DeadZero : Number of dead trees at first visit / model input InfZero : Number of currently infested trees at first visit / model input DeadHog : Number of dead trees estimated by the model InfHog : Number of currently infested trees estimated by the model DeadDen : Number of dead trees recorded in Den field data InfDen : Number of infested trees recorded in Den field data // Here are the equations. ResInfDen = Infested - InfDen; ResDeadDen = Dead - DeadDen; ResInfHog = Infested - InfHog; ResDeadHog = Dead - DeadHog; ResInfDenHog = InfDen - InfHog; ResDeadDenHog = DeadDen - DeadHog; PErrInfDen = 100 * (Infested - InfDen) / Infested; PErrDeadDen = 100 * (Dead - DeadDen) / Dead; PErrInfHog = 100 * (Infested - InfHog) / Infested; PErrDeadHog = 100 * (Dead - DeadHog) / Dead; PErrInfDenHog = 100 * (InfDen - InfHog) / InfDen; PErrDeadDenHog = 100 * (DeadDen - DeadHog) / DeadDen; AbPErrInfDen = 100 * ABS((Infested - InfDen) / Infested); AbPErrDeadDen = 100 * ABS((Dead - DeadDen) / Dead); AbPErrInfHog = 100 * ABS((Infested - InfHog) / Infested); AbPErrDeadHog = 100 * ABS((Dead - DeadHog) / Dead); AbPErrInfDenHog = 100 * ABS((InfDen - InfHog) / InfDen); AbPErrDeadDenHog = 100 * ABS((DeadDen - DeadHog) / DeadDen);--> <!-- // Match root of input SPBModel Xml --><xsl:template match="/SPBModel">
<table>
<tr>
<th>SpotName</th>
<th>SimDay</th>
<th>Date</th>
<th>OrdDay</th>
<th>Temp</th>
<th>InfDen</th>
<th>DeadDen</th>
<th>InfHog</th>
<th>DeadHog</th>
<th>ResInfDen</th>
<th>ResDeadDen</th>
<th>ResInfHog</th>
<th>ResDeadHog</th>
<th>ResInfDenHog</th>
<th>ResDeadDenHog</th>
<th>PErrInfDen</th>
<th>PErrDeadDen</th>
<th>PErrInfHog</th>
<th>PErrDeadHog</th>
<th>PErrInfDenHog</th>
<th>PErrDeadDenHog</th>
<!--<th>AbPErrInfDen</th> <th>AbPErrDeadDen</th> <th>AbPErrInfHog</th> <th>AbPErrDeadHog</th> <th>AbPErrInfDenHog</th> <th>AbPErrDeadDenHog</th>--></tr>
<!-- // For each batch --><xsl:apply-templates select="/SPBModel/Batch"/>
</table>
</xsl:template>
<xsl:template match="SPBModel/Batch">
<xsl:variable name="SpotName" select="BatchName"/>
<xsl:variable name="DateZero" select="substring-before(./Frame[IsModelInputFrame][1]/StartDate, 'T')"/>
<xsl:variable name="InfZero" select="./Frame[IsModelInputFrame][1]/CurrentlyInfested"/>
<xsl:variable name="DeadZero" select="number(./Frame[IsModelInputFrame][1]/PreviouslyInfested) + number($InfZero)"/>
<!-- // For each frame in this batch--><xsl:for-each select="Frame">
<xsl:variable name="FrameDate" select="StartDate"/>
<xsl:variable name="InfDen" select="CurrentlyInfested"/>
<xsl:variable name="DeadDen" select="number(PreviouslyInfested) + number($InfDen)"/>
<xsl:variable name="InfHog" select="../Frame[IsModelInputFrame][1]/EngineOutput[GregorianDateTime=$FrameDate][1]/TreesInfested"/>
<xsl:variable name="DeadHog" select="../Frame[IsModelInputFrame][1]/EngineOutput[GregorianDateTime=$FrameDate][1]/TreesDead"/>
<xsl:variable name="SimDay" select="../Frame[IsModelInputFrame][1]/EngineOutput[GregorianDateTime=$FrameDate][1]/SimulationDay"/>
<xsl:variable name="OrdDay" select="../Frame[IsModelInputFrame][1]/EngineOutput[GregorianDateTime=$FrameDate][1]/OrdinalDay"/>
<tr>
<td>
<!-- // Visit Name --><xsl:value-of select="FrameName"/>
</td>
<td>
<!-- // Elapsed Days --><xsl:value-of select="$SimDay + 1"/>
</td>
<td>
<!-- // Visit Date --><xsl:value-of select="substring-before($FrameDate, 'T')"/>
</td>
<td>
<!-- // Ordinal Day --><xsl:value-of select="$OrdDay"/>
</td>
<td>
<!-- // Temperature --><xsl:value-of select="../Frame[IsModelInputFrame][1]/EngineOutput[GregorianDateTime=$FrameDate][1]/Temperature"/>
</td>
<td>
<!-- // InfDen --><xsl:value-of select="round($InfDen)"/>
</td>
<td>
<!-- // DeadDen --><xsl:value-of select="round($DeadDen)"/>
</td>
<td>
<!-- // InfHog --><xsl:value-of select="round($InfHog)"/>
</td>
<td>
<!-- // DeadHog --><xsl:value-of select="round($DeadHog)"/>
</td>
<td>
<!-- // ResInfDen --><xsl:value-of select="round($InfZero - $InfDen)"/>
</td>
<td>
<!-- // ResDeadDen --><xsl:value-of select="round($DeadZero - $DeadDen)"/>
</td>
<td>
<!-- // ResInfHog --><xsl:value-of select="round($InfZero - $InfHog)"/>
</td>
<td>
<!-- // ResDeadHog --><xsl:value-of select="round($DeadZero - $DeadHog)"/>
</td>
<td>
<!-- // ResInfDenHog --><xsl:value-of select="round($InfDen - $InfHog)"/>
</td>
<td>
<!-- // ResDeadDenHog --><xsl:value-of select="round($DeadDen - $DeadHog)"/>
</td>
<td>
<!-- // PErrInfDen --><xsl:value-of select="100 * ($InfZero - $InfDen) div $InfZero"/>
</td>
<td>
<!-- // PErrDeadDen --><xsl:value-of select="100 * ($DeadZero - $DeadDen) div $DeadZero"/>
</td>
<td>
<!-- // PErrInfHog --><xsl:value-of select="100 * ($InfZero - $InfHog) div $InfZero"/>
</td>
<td>
<!-- // PErrDeadHog --><xsl:value-of select="100 * ($DeadZero - $DeadHog) div $DeadZero"/>
</td>
<td>
<!-- // PErrInfDenHog --><xsl:value-of select="100 * ($InfDen - $InfHog) div $InfDen"/>
</td>
<td>
<!-- // PErrDeadDenHog --><xsl:value-of select="100 * ($DeadDen - $DeadHog) div $DeadDen"/>
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>