source: main/trunk/ibisph-view/src/main/webapp/xslt/xml/Interactive.xslt @ 24408

Last change on this file since 24408 was 24408, checked in by GarthBraithwaite_STG, 13 months ago

view - temp commit. Updated leaflet js comments. Added formatter to leaflet control code - not fully implemented/tested. Updated RECORD_DIMENSION_FIELD/RECORD_FIELD_NAME to NAME.

File size: 17.0 KB
Line 
1<?xml version="1.0" encoding="ISO-8859-1"?>
2
3<xsl:stylesheet version="3.0" 
4        xmlns:xsl ="http://www.w3.org/1999/XSL/Transform" 
5        xmlns:xs  ="http://www.w3.org/2001/XMLSchema"
6        xmlns:ibis="http://www.ibisph.org"
7
8        exclude-result-prefixes="ibis xs xsl"
9>
10
11        <ibis:doc>
12                <name>xml/Interactive</name>
13                <summary>Provides XML elements used by Kendo and Leaflet XSLT</summary>
14                <description>
15                        Provides XSLT templates used to produce RECORD_DIMENSION_FIELD,
16                        RECORD_ANCILLARY_VALUE_FIELD, filter down IP View DATASET_RECORDs,
17                        and misc calls like unique, sorted, csvDimensionsTitleList. 
18
19                        These structures are used by the JSON processing XSLT code which is
20                        then passed to the specific Kendo and Leaflet js code.  These templates
21                        could have been named "DataViz" but this would be confusing when trying
22                        to maintain. 
23
24                        The IP view or QM result page templates define the containers and
25                        control how structures and script as to be built and applied.  The
26                        way this works is that the IP or QM XSLT page code get these
27                        Interactive XML structures and then pass them to more specific JSON
28                        producing XSLT templates which localize processing of those generic
29                        structs into JSON.  The JSON structs are then passed to the general
30                        DataViz script templates.
31                </description>
32        </ibis:doc>
33
34
35        <xsl:template name="Interactive.recordDimensionFields" 
36                ibis:doc="Creates the following struct for series, cat, and const:
37
38                        RECORD_DIMENSION_FIELD
39                                NAME  - used for the data array/datasource fieldname
40                                TITLE - used for kendo chart series and cat title.
41                                DIMENSION_USAGE - series, category, constant
42                                DIMENSION_NAMES
43                                        DIMENSION_NAME
44                                DIMENSION_VALUES_COUNT - number of dimension values to determine use.
45                                        if count = 1 or 0 then don't have to do any special
46                                        constant or group handling.
47
48                        This struct is then passed into the Interactive.indicatorViewDatasetRecords
49                        (QM dataset records are ready to go) to filter dataset records according
50                        to usage and dimensions.
51                        recordDimensionFields
52                "
53        >
54                <xsl:param name="dimensions"/>
55                <xsl:param name="dimensionUsages"/>
56
57                <xsl:call-template name="Interactive.recordDimensionField">
58                        <xsl:with-param name="usage"     select="'series'"/>
59                        <xsl:with-param name="fieldName" select="'Series'"/>
60                        <xsl:with-param name="dimensions"      select="$dimensions"/>
61                        <xsl:with-param name="dimensionUsages" select="$dimensionUsages"/>
62                </xsl:call-template>
63                <xsl:call-template name="Interactive.recordDimensionField">
64                        <xsl:with-param name="usage"     select="'category'"/>
65                        <xsl:with-param name="fieldName" select="'Category'"/>
66                        <xsl:with-param name="dimensions"      select="$dimensions"/>
67                        <xsl:with-param name="dimensionUsages" select="$dimensionUsages"/>
68                </xsl:call-template>
69                <xsl:call-template name="Interactive.recordDimensionField">
70                        <xsl:with-param name="usage"     select="'constant'"/>
71                        <xsl:with-param name="fieldName" select="'Constant'"/>
72                        <xsl:with-param name="dimensions"      select="$dimensions"/>
73                        <xsl:with-param name="dimensionUsages" select="$dimensionUsages"/>
74                </xsl:call-template>
75        </xsl:template>
76
77        <xsl:template name="Interactive.recordDimensionField">
78                <xsl:param name="usage"/>
79                <xsl:param name="fieldName"/>
80                <xsl:param name="dimensions"/>
81                <xsl:param name="dimensionUsages"/>
82
83                <RECORD_DIMENSION_FIELD>
84                        <NAME><xsl:value-of select="$fieldName"/></NAME>
85                        <TITLE>
86                                <xsl:call-template name="Interactive.csvDimensionsTitleList">
87                                        <xsl:with-param name="dimensions" select="$dimensions//DIMENSION
88                                                [NAME = $dimensionUsages//DIMENSION_USAGE[USAGE=$usage]/NAME]"
89                                        />
90                                </xsl:call-template>
91                        </TITLE>
92                        <DIMENSION_USAGE><xsl:value-of select="$usage"/></DIMENSION_USAGE>
93                        <DIMENSION_NAMES>
94                                <xsl:for-each select="$dimensionUsages//DIMENSION_USAGE[USAGE=$usage]">
95                                <DIMENSION_NAME><xsl:value-of select="NAME"/></DIMENSION_NAME>
96                                </xsl:for-each>
97                        </DIMENSION_NAMES>
98                        <DIMENSION_VALUES_COUNT><xsl:value-of select="count($dimensionUsages//DIMENSION_USAGE[USAGE=$usage]/VALUES/VALUE)"/></DIMENSION_VALUES_COUNT>
99                </RECORD_DIMENSION_FIELD>
100        </xsl:template>
101
102
103        <xsl:template name="Interactive.mapRecordDimensionFilters" 
104                ibis:doc="Creates the map dimension filter XML struct that the
105                        LeafletMap.xslt uses to create the map data record json dim filter.
106                        Struct returns 1-3 RECORD_DIMENSION_FILTER structs.
107                "
108        >
109                <xsl:param name="geoDimensionName"/>   
110                <xsl:param name="dimensions"/> 
111                <xsl:param name="dimensionUsages" ibis:doc="
112                                DIMENSION_USAGE
113                                        USAGE category/series/constant/
114                                        NAME  GeoCnty - dimension name
115                                        VALUES
116                                                VALUE  dimension value SORT_ORDER
117                        "
118                />
119                <xsl:param name="recordDimensionFields" ibis:doc="`
120                                generic, internal ser/cat/const struct:
121                                RECORD_DIMENSION_FIELD
122                                        DIMENSION_USAGE category/series/constant - differs from NAME in NOT camel case and matches the DIMENSION_USAGE/NAME
123                                        NAME  Category/Series/Constant - differs from usage in that it is camel case via the XSLT code when creating this struct/NAME
124                                        TITLE
125                                        DIMENSION_NAMES
126                                                DIMENSION_NAME GeoCnty/DIMENSION_NAME
127                                        DIMENSION_VALUES_COUNT 3 - convienence value
128                        "
129                />
130
131                <xsl:param name="geoDimensionUsage"    select="$dimensionUsages/DIMENSION_USAGE[NAME = $geoDimensionName]"/>
132                <xsl:param name="periodDimensionUsage" select="$dimensionUsages/DIMENSION_USAGE[NAME = $dimensions/DIMENSION[exists(PERIOD_FLAG)]/NAME][1]"/>
133
134                <xsl:param name="otherDimensionUsage"  select="$dimensionUsages/DIMENSION_USAGE[USAGE != $geoDimensionUsage/USAGE] except $periodDimensionUsage"/>
135
136                <xsl:call-template name="Interactive.mapRecordDimensionFilter">
137                        <xsl:with-param name="recordDimensionFields" select="$recordDimensionFields"/>
138                        <xsl:with-param name="dimensionUsage" select="$geoDimensionUsage"/>
139                        <xsl:with-param name="dimension" select="$dimensions/DIMENSION[NAME=$geoDimensionUsage/NAME]"/>
140                </xsl:call-template>
141                <xsl:call-template name="Interactive.mapRecordDimensionFilter">
142                        <xsl:with-param name="recordDimensionFields" select="$recordDimensionFields"/>
143                        <xsl:with-param name="dimensionUsage" select="$periodDimensionUsage"/>
144                        <xsl:with-param name="dimension" select="$dimensions/DIMENSION[NAME=$periodDimensionUsage/NAME]"/>
145                </xsl:call-template>
146                <xsl:call-template name="Interactive.mapRecordDimensionFilter">
147                        <xsl:with-param name="recordDimensionFields" select="$recordDimensionFields"/>
148                        <xsl:with-param name="dimensionUsage" select="$otherDimensionUsage"/>
149                        <xsl:with-param name="dimension" select="$dimensions/DIMENSION[NAME=$otherDimensionUsage[1]/NAME]"/>
150                </xsl:call-template>
151        </xsl:template> 
152
153        <xsl:template name="Interactive.mapRecordDimensionFilter" 
154                ibis:doc="helper to locaize create actual XML map dimension inclusion struct.
155                        The fieldname is used by the script to access the data record's
156                        geo dim.  Here's the struct of a JSON data record:
157                                'rowID':'31'
158                                ,'Category':'GeoCnty.61'
159                                ,'CategoryTitle':'Valencia'
160                                ,'CategorySortOrder':33
161                                ,'Constant':'YearGrp3Yrs.2017'
162                                ,'ConstantTitle':'2015-2017'
163                                ,'ConstantSortOrder':2015
164                                ,'MeasureValue': 10.5
165                                ,'MeasureValueTitle':'10.5%'
166                "
167        >
168                <xsl:param name="recordDimensionFields" ibis:doc="generic, internal ser/cat/const struct."/>
169                <xsl:param name="dimensionUsage"        ibis:doc="Indicator View or QM DIMENSION_USAGE struct."/>
170                <xsl:param name="dimension"             ibis:doc="dimensions/DIMENSION[NAME=$dimensionUsage/NAME]"/>
171 
172                <xsl:param name="dimensionValues" select="$dimension/VALUES/VALUE[not(NOT_SELECTABLE_FLAG) and (ibis:getNormalizedText(.) = $dimensionUsage//VALUE)]"/>
173                <xsl:param name="dimensionValue">
174                        <xsl:choose>
175                                <!-- geo has no dim no value.  Process for geo flag so no otherwise -->
176                                <xsl:when test="exists($dimension/GEOGRAPHY_FLAG)"/>
177                                <xsl:when test="exists($dimension/PERIOD_FLAG)">
178                                        <xsl:variable name="maxPeriodValue" select="max($dimensionValues/text()[1])" />
179                                        <xsl:copy-of select="$dimensionValues[number(text()[1]) = $maxPeriodValue]"/>
180                                </xsl:when>
181                                <xsl:otherwise>
182                                        <xsl:copy-of select="$dimensionValues[1]"/>
183                                </xsl:otherwise>
184                        </xsl:choose>
185                </xsl:param>
186
187                <xsl:if test="$dimensionUsage/USAGE">
188                        <RECORD_DIMENSION_FILTER>
189                                <RECORD_DIMENSION_FIELD_NAME><xsl:value-of select="$recordDimensionFields/RECORD_DIMENSION_FIELD[DIMENSION_NAMES/DIMENSION_NAME = $dimension/NAME]/NAME"/></RECORD_DIMENSION_FIELD_NAME>
190                                <DIMENSION_NAME><xsl:value-of  select="$dimension/NAME"/></DIMENSION_NAME>
191                                <DIMENSION_TITLE><xsl:value-of select="ibis:getDimensionTitle($dimension)"/></DIMENSION_TITLE>
192                                <DIMENSION_VALUE><xsl:value-of select="ibis:getNormalizedText($dimensionValue/VALUE)"/></DIMENSION_VALUE>
193                                <DIMENSION_VALUE_TITLE><xsl:value-of select="ibis:getDimensionValueTitle($dimensionValue/VALUE)"/></DIMENSION_VALUE_TITLE>
194                        </RECORD_DIMENSION_FILTER>
195                </xsl:if>
196        </xsl:template>
197
198
199        <xsl:template name="Interactive.indicatorViewDatasetRecords"
200                ibis:doc="Creates a subset of the dataset records by filtering out the
201                        unused dataset records.  This template loops all possible dataset
202                        records and filters out based on the supplied cat, series, const
203                        dimensions and values usages to create the data record subset.
204
205                        This dataset record filtering uses the dimension usages to determine
206                        if the usage and dim name/values match.
207
208                        This is typically only used for the IPV uses because QM datasets are
209                        very specific, alreaady filtered records.
210                "
211        >
212                <xsl:param name="dimensionUsages"       ibis:doc="Indicator View DIMENSION_USAGE struct that is used to filter records."/>
213                <xsl:param name="datasetRecords"        ibis:doc="typically the entire indicator's DATASET//RECORDS struct."/>
214                <xsl:param name="recordDimensionFields" ibis:doc="generic, internal ser/cat/const struct."/>
215
216                <xsl:variable name="categoryDimensionUsages" select="$dimensionUsages/DIMENSION_USAGE[USAGE='category']"/>
217                <xsl:variable name="seriesDimensionUsages"   select="$dimensionUsages/DIMENSION_USAGE[USAGE='series']"/>
218                <xsl:variable name="constantDimensionUsages" select="$dimensionUsages/DIMENSION_USAGE[USAGE='constant']"/>
219
220                <!-- no hasCatRecDimValues is not needed - required will always have -->
221                <xsl:variable name="seriesRecordDimensionValuesCount"   select="$recordDimensionFields/RECORD_DIMENSION_FIELD[DIMENSION_USAGE='series']/DIMENSION_VALUES_COUNT"   as="xs:integer"/>
222                <xsl:variable name="constantRecordDimensionValuesCount" select="$recordDimensionFields/RECORD_DIMENSION_FIELD[DIMENSION_USAGE='constant']/DIMENSION_VALUES_COUNT" as="xs:integer"/>
223
224                <!-- used to filter/limit ds records that only have the same # of dims -->
225                <xsl:variable name="dimensionUsagesCount" select="count(distinct-values($dimensionUsages/DIMENSION_USAGE/USAGE))"/>
226
227                <!-- might as well filter out records that don't have the same number of dims. -->
228                <xsl:for-each select="$datasetRecords/RECORD[count(DIMENSIONS/DIMENSION) = $dimensionUsagesCount]">
229                        <xsl:variable name="datasetRecord" select="."/>
230
231                        <!-- NORMALIZE-SPACE: usage VALUE has text() and SORT_ORDER so is needed. -->
232                        <xsl:variable name="categoryDimensionUsage" select="$categoryDimensionUsages [NAME = $datasetRecord//DIMENSION/NAME]"/>
233                        <xsl:variable name="categoryRecordDimensionValueCount" select="count($datasetRecord//DIMENSION[NAME = $categoryDimensionUsage/NAME]/VALUE[text() = $categoryDimensionUsage/VALUES/VALUE/normalize-space(text()[1])])"/>
234
235                        <xsl:variable name="seriesDimensionUsage"   select="$seriesDimensionUsages   [NAME = $datasetRecord//DIMENSION/NAME]"/>
236                        <xsl:variable name="seriesRecordDimensionValueCount"   select="count($datasetRecord//DIMENSION[NAME = $seriesDimensionUsage/NAME]/VALUE[text() =  $seriesDimensionUsage/VALUES/VALUE/normalize-space(text()[1])])"/>
237
238                        <xsl:variable name="constantDimensionUsage" select="$constantDimensionUsages [NAME = $datasetRecord//DIMENSION/NAME]"/>
239                        <xsl:variable name="constantRecordDimensionValueCount" select="count($datasetRecord//DIMENSION[NAME = $constantDimensionUsage/NAME]/VALUE[text() = $constantDimensionUsage/VALUES/VALUE/normalize-space(text()[1])])"/>
240
241                        <!-- All records have a category but to be safe check cat exists.
242                                If constant and series defined for the view then the record
243                                MUST include them.  If NO series/const defined then the
244                                record MUST NOT have any series/const dimension records.
245                                Easy way to make sure that not including records that do not
246                                have the right number of dimensions is to compare counts.
247                                NOTE: 0 = value"S"count, 0 != ValueCount.
248                        -->
249                        <xsl:if test="(0 != $categoryRecordDimensionValueCount)
250                                and ((0 = $seriesRecordDimensionValuesCount)   or (0 != $seriesRecordDimensionValueCount))
251                                and ((0 = $constantRecordDimensionValuesCount) or (0 != $constantRecordDimensionValueCount))
252                        ">
253                                <xsl:copy-of select="$datasetRecord"/>
254                        </xsl:if>
255                </xsl:for-each>
256
257        </xsl:template>
258
259
260        <xsl:template name="Interactive.recordAncillaryValueFields" 
261                ibis:doc="Creates the following ancillary values fields:
262                        RECORD_ANCILLARY_VALUE_FIELD
263                                NAME  - ancillary value name
264                                TITLE - either label or title or name
265                                XSLT_FORMAT_PATTERN
266                                [INFO_FIELD_FLAG] - flag element for label and notes?????????????
267                "
268        >
269                <xsl:param name="datasetAncillaryValues"        ibis:doc="DATASET_ANCILLARY_VALUES in the QM config or IP dataset"/>
270                <xsl:param name="ancillaryValues"                       ibis:doc="complete AV defs"/>
271                <xsl:param name="valueTypes"                            ibis:doc="complete VT defs"/>
272                <xsl:param name="measureFormatPattern"          ibis:doc="from measure and value type."/>
273
274                <xsl:for-each select="$datasetAncillaryValues/DATASET_ANCILLARY_VALUE">
275                        <xsl:variable name="ancillaryValue" select="$ancillaryValues/ANCILLARY_VALUE[NAME = current()/ANCILLARY_VALUE_NAME]"/>
276                <RECORD_ANCILLARY_VALUE_FIELD>
277                        <NAME><xsl:value-of select="ANCILLARY_VALUE_NAME"/></NAME>
278                        <xsl:choose>
279                                <xsl:when test="0 != string-length(ANCILLARY_VALUE_LABEL)">
280                                        <TITLE><xsl:value-of select="ANCILLARY_VALUE_LABEL"/></TITLE>
281                                </xsl:when>
282                                <xsl:when test="0 != string-length($ancillaryValue/TITLE)">
283                                        <xsl:copy-of select="$ancillaryValue/TITLE"/>
284                                </xsl:when>
285                                <xsl:otherwise>
286                                        <TITLE><xsl:value-of select="ANCILLARY_VALUE_NAME"/></TITLE>
287                                </xsl:otherwise>
288                        </xsl:choose>
289
290                        <xsl:variable name="formatPattern" select="
291                                if( exists( ($valueTypes//VALUE_TYPE[NAME = $ancillaryValue/VALUE_TYPE_NAME]/XSLT_FORMAT_PATTERN)[1] ))
292                                then ($valueTypes//VALUE_TYPE[NAME = $ancillaryValue/VALUE_TYPE_NAME]/XSLT_FORMAT_PATTERN)[1]
293                                else $measureFormatPattern
294                        "/>
295                        <xsl:copy-of select="$formatPattern"/>
296                </RECORD_ANCILLARY_VALUE_FIELD>
297                </xsl:for-each>
298        </xsl:template>
299
300
301        <xsl:template name="Interactive.datasetRecordTotalValues"
302                ibis:doc="Creates the following struct for total dsr fields - used for
303                        query result total rows. 
304
305                        DATASET_RECORD_TOTAL_VALUE
306                                NAME  - 'Measure' or ANCILLARY_VALUE_NAME
307                                TITLE - formatted value.
308
309                        Called from DataViz.populateKendoLeafletDataVizObject if showGrid
310                "
311        >
312                <xsl:param name="datasetRecords"/>
313                <xsl:param name="recordAncillaryValueFields"/>
314                <xsl:param name="measureFormatPattern"/>
315                <xsl:param name="totalDimensionValue" select="'.'"/>
316
317                <xsl:variable name="totalDatasetRecord" select="$datasetRecords/RECORD[not(DIMENSIONS/DIMENSION/VALUE/text() != $totalDimensionValue)]"/>
318                <xsl:if test="(1 = count($totalDatasetRecord)) and (0 != string-length($totalDatasetRecord/MEASURE/VALUE))">
319                        <DATASET_RECORD_TOTAL_VALUE>
320                                <NAME>Measure</NAME>
321                                <TITLE><xsl:value-of select="ibis:getFormattedNumber($totalDatasetRecord/MEASURE/VALUE, $measureFormatPattern)"/></TITLE>
322                        </DATASET_RECORD_TOTAL_VALUE>
323
324                        <xsl:for-each select="$recordAncillaryValueFields/RECORD_ANCILLARY_VALUE_FIELD">
325                                <xsl:variable name="ancillaryValue" select="$totalDatasetRecord//ANCILLARY_VALUE[NAME=current()/NAME]/VALUE"/>
326                        <DATASET_RECORD_TOTAL_VALUE>
327                                <xsl:copy-of select="NAME"/> 
328                                <TITLE><xsl:value-of select="ibis:getFormattedNumber($ancillaryValue, XSLT_FORMAT_PATTERN)"/></TITLE>
329                        </DATASET_RECORD_TOTAL_VALUE>
330                        </xsl:for-each>
331                </xsl:if>
332        </xsl:template>
333
334
335        <xsl:template name="Interactive.csvDimensionsTitleList"
336                ibis:doc="Internal template which builds a comma separated values
337                        (CSV) list of unique dimension label/titles. 
338                "
339        >
340                <xsl:param name="dimensions" ibis:doc="dimensions to look up value titles from."/>
341
342                <xsl:variable name="dimensionTitles">
343                        <xsl:for-each select="$dimensions">
344                                <xsl:sort select="SORT_ORDER" order="ascending" data-type="number"/>
345                                <xsl:sort select="TITLE"      order="ascending" data-type="text"/>
346                                <TITLE><xsl:value-of select="ibis:getDimensionTitle(.)"/></TITLE>
347                        </xsl:for-each>
348                </xsl:variable>
349                <xsl:for-each select="distinct-values($dimensionTitles/TITLE)">
350                        <xsl:if test="position() != 1">, </xsl:if>
351                        <xsl:value-of select="."/>
352                </xsl:for-each>
353        </xsl:template>
354
355</xsl:stylesheet>
356<!-- ============================= End of File ============================= -->
Note: See TracBrowser for help on using the repository browser.