v4postprocessing.xslt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--
  3. /*****************************************************************************
  4. * Licensed Materials - Property of IBM
  5. *
  6. * IBM Cognos Products: migv4
  7. *
  8. * (C) Copyright IBM Corp. 2003, 2011.
  9. *
  10. * US Government Users Restricted Rights - Use, duplication or disclosure
  11. * restricted by GSA ADP Schedule Contract with IBM Corp.
  12. ****************************************************************************/
  13. -->
  14. <?xml-stylesheet type="text/xsl" ?>
  15. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  16. xmlns:fo="http://www.w3.org/1999/XSL/Format"
  17. xmlns:str="http://www.ora.com/XSLTCookbook/namespaces/strings"
  18. xmlns="http://developer.cognos.com/schemas/report/1/"
  19. xmlns:v4="http://developer.cognos.com/schemas/report/1/"
  20. exclude-result-prefixes="xsl fo str v4">
  21. <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
  22. <!-- copy all children nodes -->
  23. <xsl:template match=" node() | @* | comment() | processing-instruction()">
  24. <xsl:copy>
  25. <xsl:apply-templates select="node() | @*"/>
  26. </xsl:copy>
  27. </xsl:template>
  28. <xsl:variable name="MSQ5" select="'Master_Section_Query5'"/>
  29. <!-- =============================================================================== -->
  30. <!-- resolve dangling data items directly in Master_Selection_Query5 -->
  31. <!-- preprocess Master Selection Query5 -->
  32. <xsl:template match="v4:BIQuery[ @name = $MSQ5 ]">
  33. <xsl:copy>
  34. <xsl:apply-templates select="@*"/>
  35. <xsl:for-each select="*">
  36. <xsl:choose>
  37. <!-- cube node -->
  38. <xsl:when test="local-name()='cube'">
  39. <xsl:copy>
  40. <xsl:apply-templates select="@*"/>
  41. <!-- get factList nodes -->
  42. <xsl:variable name="factListExists" select="v4:factList"/>
  43. <xsl:variable name="cubechildren" select="./*"/>
  44. <xsl:for-each select="$cubechildren">
  45. <xsl:choose>
  46. <!-- if factList node exists, copy existing items. then add new ones -->
  47. <xsl:when test="local-name()='factList'">
  48. <xsl:copy>
  49. <xsl:apply-templates select="@*"/>
  50. <xsl:apply-templates select="*"/>
  51. <xsl:call-template name="processExpressions"/>
  52. <xsl:call-template name="processQueryItemRef"/>
  53. </xsl:copy>
  54. </xsl:when>
  55. <xsl:when test="local-name()='dimension'">
  56. <xsl:if test="count($factListExists) &gt; 0">
  57. <xsl:copy>
  58. <xsl:apply-templates select="@*"/>
  59. <xsl:apply-templates select="node() | comment() | processing-instruction()"/>
  60. </xsl:copy>
  61. </xsl:if>
  62. <xsl:if test="count($factListExists) = 0">
  63. <xsl:copy>
  64. <xsl:apply-templates select="@*"/>
  65. <xsl:variable name="levels" select="v4:level"/>
  66. <xsl:for-each select="$levels">
  67. <xsl:choose>
  68. <xsl:when test="position() &lt; count($levels)">
  69. <xsl:copy-of select="."/>
  70. </xsl:when>
  71. <xsl:otherwise>
  72. <xsl:copy>
  73. <xsl:apply-templates select="node() | @* | comment() | processing-instruction()"/>
  74. <xsl:call-template name="processExpressions"/>
  75. <xsl:call-template name="processQueryItemRef"/>
  76. </xsl:copy>
  77. </xsl:otherwise>
  78. </xsl:choose>
  79. </xsl:for-each>
  80. </xsl:copy>
  81. </xsl:if>
  82. </xsl:when>
  83. <!-- for all other nodes, copy them -->
  84. <xsl:otherwise>
  85. <xsl:apply-templates select="."/>
  86. </xsl:otherwise>
  87. </xsl:choose>
  88. </xsl:for-each>
  89. </xsl:copy>
  90. </xsl:when>
  91. <!-- tabularModel node -->
  92. <xsl:when test="local-name()='tabularModel'">
  93. <xsl:copy>
  94. <!-- copy all existing attributes and nodes -->
  95. <xsl:apply-templates select="node() | @* | comment() | processing-instruction()"/>
  96. <!-- add new dataItems for expressions -->
  97. <xsl:call-template name="processExpressions">
  98. <xsl:with-param name="nodename" select="'tabularModel'"/>
  99. </xsl:call-template>
  100. <!-- add new dataItems for queryItemRefs -->
  101. <xsl:call-template name="processQueryItemRef">
  102. <xsl:with-param name="nodename" select="'tabularModel'"/>
  103. </xsl:call-template>
  104. </xsl:copy>
  105. </xsl:when>
  106. <!-- copy all other nodes -->
  107. <xsl:otherwise>
  108. <xsl:copy>
  109. <xsl:apply-templates select="node() | @* | comment() | processing-instruction()"/>
  110. </xsl:copy>
  111. </xsl:otherwise>
  112. </xsl:choose>
  113. </xsl:for-each>
  114. </xsl:copy>
  115. </xsl:template>
  116. <!-- Process all query item references under all layout elements that refer directly to Master Section Query5 -->
  117. <xsl:template name="processQueryItemRef">
  118. <xsl:param name="nodename" select="'factList'"/>
  119. <xsl:variable name="queryItemRefs" select="//v4:layout//*[ @refQuery = $MSQ5 ]//v4:queryItemRef"/>
  120. <xsl:for-each select="$queryItemRefs">
  121. <!-- only process the direct children of master query5 -->
  122. <xsl:if test="count(./ancestor::*[@refQuery]) = 1">
  123. <!-- check if the same quertItemRef was processed already -->
  124. <xsl:variable name="curpos" select="position()"/>
  125. <xsl:variable name="refItem" select="@refItem"/>
  126. <xsl:variable name="existed">
  127. <xsl:for-each select="$queryItemRefs">
  128. <xsl:if test="position() &lt; $curpos">
  129. <xsl:if test="count(./ancestor::*[@refQuery]) = 1 and @refItem = $refItem">
  130. <xsl:value-of select="'1'"/>
  131. </xsl:if>
  132. </xsl:if>
  133. </xsl:for-each>
  134. </xsl:variable>
  135. <xsl:if test="not (contains($existed, '1'))">
  136. <!-- add new items to factList -->
  137. <xsl:if test="$nodename = 'factList'">
  138. <xsl:call-template name="findFactList">
  139. <xsl:with-param name="queryname" select="@refItem"/>
  140. </xsl:call-template>
  141. </xsl:if>
  142. <!-- add new dataItems to tabularModel -->
  143. <xsl:if test="$nodename = 'tabularModel'">
  144. <xsl:call-template name="findDataItem">
  145. <xsl:with-param name="queryname" select="@refItem"/>
  146. </xsl:call-template>
  147. </xsl:if>
  148. </xsl:if>
  149. </xsl:if>
  150. </xsl:for-each>
  151. </xsl:template>
  152. <!-- Process all expressions under all layout elements that refer directly to Master Section Query5 -->
  153. <xsl:template name="processExpressions">
  154. <xsl:param name="nodename" select="'factList'"/>
  155. <xsl:variable name="expressions" select="//v4:layout//*[ @refQuery = $MSQ5 ]//v4:expression"/>
  156. <xsl:for-each select="$expressions">
  157. <xsl:if test="count(./ancestor::*[@refQuery]) = 1">
  158. <xsl:call-template name="processExpression">
  159. <xsl:with-param name="nodename" select="$nodename"/>
  160. <xsl:with-param name="expression" select="."/>
  161. <xsl:with-param name="expressions" select="$expressions"/>
  162. <xsl:with-param name="curpos" select="position()"/>
  163. </xsl:call-template>
  164. </xsl:if>
  165. </xsl:for-each>
  166. </xsl:template>
  167. <!-- process one expression -->
  168. <xsl:template name="processExpression">
  169. <xsl:param name="nodename" select="'factList'"/>
  170. <xsl:param name="expression"/>
  171. <xsl:param name="expressions"/>
  172. <xsl:param name="curpos" select="1"/>
  173. <xsl:variable name="qiName" select="substring-after(substring-before($expression, ']'), '[')"/>
  174. <xsl:if test="string-length($qiName) &gt; 0 and $qiName != ''">
  175. <!-- check if the same quertItemRef was processed already -->
  176. <xsl:variable name="existed">
  177. <xsl:for-each select="$expressions">
  178. <xsl:if test="position() &lt; $curpos">
  179. <xsl:if test="count(./ancestor::*[@refQuery]) = 1 and contains(./text(), concat('[',$qiName,']'))">
  180. <xsl:value-of select="'1'"/>
  181. </xsl:if>
  182. </xsl:if>
  183. </xsl:for-each>
  184. <xsl:if test="contains( substring-before($expressions[$curpos]/text(),$expression), concat('[',$qiName,']'))">
  185. <xsl:value-of select="'1'"/>
  186. </xsl:if>
  187. </xsl:variable>
  188. <xsl:if test="not (contains( $existed, '1'))">
  189. <xsl:if test="$nodename = 'factList'">
  190. <!-- add a new item to factList -->
  191. <xsl:call-template name="findFactList">
  192. <xsl:with-param name="queryname" select="$qiName"/>
  193. </xsl:call-template>
  194. </xsl:if>
  195. <xsl:if test="$nodename = 'tabularModel'">
  196. <!-- add a new dataItem to tabularModel -->
  197. <xsl:call-template name="findDataItem">
  198. <xsl:with-param name="queryname" select="$qiName"/>
  199. </xsl:call-template>
  200. </xsl:if>
  201. </xsl:if>
  202. </xsl:if>
  203. <xsl:if test="contains(substring-after($expression, ']'), '[')">
  204. <!-- recursive call to process remainder of $expression -->
  205. <xsl:call-template name="processExpression">
  206. <xsl:with-param name="nodename" select="'factList'"/>
  207. <xsl:with-param name="expression" select="substring-after($expression, ']')"/>
  208. <xsl:with-param name="expressions"/>
  209. <xsl:with-param name="curpos" select="$curpos"/>
  210. </xsl:call-template>
  211. </xsl:if>
  212. </xsl:template>
  213. <xsl:template name="findFactList">
  214. <xsl:param name="queryname"/>
  215. <xsl:variable name="item" select="//v4:BIQuery//v4:cube//v4:item[ @refItem = $queryname ]"/>
  216. <xsl:if test="count($item) &gt; 0">
  217. <xsl:variable name="parentquery" select="$item/ancestor::v4:BIQuery[ @name = $MSQ5 ]"/>
  218. <xsl:if test="count($parentquery) = 0">
  219. <xsl:copy-of select="$item[1]"/>
  220. </xsl:if>
  221. </xsl:if>
  222. </xsl:template>
  223. <xsl:template name="findDataItem">
  224. <xsl:param name="queryname"/>
  225. <xsl:variable name="item" select="//v4:BIQuery//v4:tabularModel/v4:dataItem[ @name = $queryname ]"/>
  226. <xsl:if test="count($item) &gt; 0">
  227. <xsl:variable name="parentquery" select="$item/ancestor::v4:BIQuery[ @name = $MSQ5 ]"/>
  228. <xsl:if test="count($parentquery) = 0">
  229. <xsl:copy-of select="$item[1]"/>
  230. </xsl:if>
  231. </xsl:if>
  232. </xsl:template>
  233. <!-- =============================================================================== -->
  234. <!-- BUG FIX 488862
  235. Apparently, customers are somewhat miffed that all query item references on their cover pages and page
  236. headers / footers are being translated into '[Data item out of Query Scope: ... ]' text items. This section attempts
  237. to assign the most appropriate query to the page so that these dangling data items suddenly have scope.
  238. This fix does not address all dangling data items. In the case where data items from two or more queries are
  239. found on the cover page or page header/footer, this algorithm will select the query that contains the greatest
  240. number of these data items. All other data items will be translated into text items as above.
  241. -->
  242. <xsl:template match="v4:pageSet/v4:page">
  243. <!-- This template examines the layout page contents for dangling data items.
  244. If found, it sets @refQuery attribute to name of most appropriate query.
  245. -->
  246. <xsl:copy>
  247. <xsl:copy-of select="@*"/>
  248. <xsl:choose>
  249. <xsl:when test="@refQuery">
  250. <!-- Cannot replace existing refQuery attribute -->
  251. </xsl:when>
  252. <xsl:when test="ancestor::v4:pageSet/@refQuery">
  253. <!-- Copy refQuery from pageSet -->
  254. <xsl:attribute name="refQuery"><xsl:value-of select="ancestor::v4:pageSet/@refQuery"/></xsl:attribute>
  255. </xsl:when>
  256. <xsl:when test=".//v4:queryItemRef[count(ancestor::v4:*/@refQuery) = 0] or .//v4:expression[count(ancestor::v4:*/@refQuery) = 0]">
  257. <!-- Add refQuery attribute for dangling data items -->
  258. <!--DBG- -><xsl:call-template name="findBestQuery"/-->
  259. <xsl:variable name="bestQuery"><xsl:call-template name="findBestQuery"/></xsl:variable>
  260. <xsl:if test="$bestQuery != ''">
  261. <xsl:attribute name="refQuery"><xsl:value-of select="$bestQuery"/></xsl:attribute>
  262. </xsl:if>
  263. </xsl:when>
  264. <xsl:otherwise>
  265. <!-- Cannot find any dangling items: therefore, nothing to do! -->
  266. </xsl:otherwise>
  267. </xsl:choose>
  268. <!-- Process remainder of page -->
  269. <xsl:apply-templates/>
  270. </xsl:copy>
  271. </xsl:template>
  272. <!-- = = = = = = = = = = = = = = = = = = = = = = = = = -->
  273. <xsl:template match="v4:promptPageList/v4:page">
  274. <!-- This template examines the prompt page contents for dangling data items.
  275. If found, it sets @refQuery attribute to name of most appropriate query.
  276. -->
  277. <xsl:copy>
  278. <xsl:copy-of select="@*"/>
  279. <xsl:choose>
  280. <xsl:when test="@refQuery">
  281. <!-- Cannot replace existing refQuery attribute -->
  282. </xsl:when>
  283. <xsl:when test=".//v4:queryItemRef[count(ancestor::v4:*/@refQuery) = 0] or .//v4:expression[count(ancestor::v4:*/@refQuery) = 0]">
  284. <!-- Add refQuery attribute for dangling data items -->
  285. <xsl:variable name="bestQuery"><xsl:call-template name="findBestQuery">
  286. <xsl:with-param name="queryList" select=".//v4:*/@refQuery"/>
  287. </xsl:call-template></xsl:variable>
  288. <xsl:if test="$bestQuery != ''">
  289. <xsl:attribute name="refQuery"><xsl:value-of select="$bestQuery"/></xsl:attribute>
  290. </xsl:if>
  291. </xsl:when>
  292. <xsl:otherwise>
  293. <!-- Cannot find any dangling items: therefore, nothing to do! -->
  294. </xsl:otherwise>
  295. </xsl:choose>
  296. <!-- Process remainder of page -->
  297. <xsl:apply-templates/>
  298. </xsl:copy>
  299. </xsl:template>
  300. <!-- === === === === === === === === === === === === === === === -->
  301. <xsl:template name="findBestQuery">
  302. <!-- queries referenced on page -->
  303. <xsl:param name="queryList" select="ancestor::v4:pageSet//v4:*/@refQuery"/>
  304. <!-- dangling data items -->
  305. <xsl:param name="queryItemRefs" select=".//v4:queryItemRef[count(ancestor::v4:*/@refQuery) = 0]/@refItem"/>
  306. <!-- dangling data items in expressions -->
  307. <xsl:param name="expressions" select=".//v4:expression[count(ancestor::v4:*/@refQuery) = 0]"/>
  308. <!-- This template examines all queries referenced in the page set to determine the most appropriate query for
  309. the refQuery attribute. The 'best query' is the BIQuery that contains the most items that are referenced in
  310. the queryItemRefs[] and expressions[] collections. Each query is examined by recursive TestBestQuery
  311. template.
  312. -->
  313. <xsl:if test="$queryList">
  314. <!-- Report expressions contain zero, one or many query item references. Extract these references by
  315. perusing the syntax of the report expression (see 'extractExprItemRefs' template).
  316. -->
  317. <xsl:variable name="exprItemRefs">
  318. <xsl:call-template name="extractExprItemRefs">
  319. <xsl:with-param name="expressions" select="$expressions"/>
  320. </xsl:call-template>
  321. </xsl:variable>
  322. <!-- Initial call to recursive TestBestQuery routine.
  323. It should return the name of the most appropriate query to resolve dangling data items.
  324. -->
  325. <!--DBG- -><xsl:comment>queryList = '<xsl:value-of select="$queryList"/>'</xsl:comment-->
  326. <!--DBG- -><xsl:comment>queryItemRefs = '<xsl:value-of select="$queryItemRefs"/>'</xsl:comment-->
  327. <!--DBG- -><xsl:comment>exprItemRefs = '<xsl:value-of select="$exprItemRefs"/>'</xsl:comment-->
  328. <xsl:call-template name="TestBestQuery">
  329. <xsl:with-param name="queryList" select="$queryList"/>
  330. <xsl:with-param name="queryItemRefs" select="$queryItemRefs"/>
  331. <xsl:with-param name="exprItemRefs" select="$exprItemRefs"/>
  332. </xsl:call-template>
  333. </xsl:if>
  334. </xsl:template>
  335. <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  336. <xsl:template name="TestBestQuery">
  337. <xsl:param name="queryList"/> <!-- queries referenced on page -->
  338. <xsl:param name="queryItemRefs"/> <!-- dangling data items -->
  339. <xsl:param name="exprItemRefs"/> <!-- dangling data items in expressions -->
  340. <xsl:param name="bestQuery"/> <!-- 'best query' as nominated (thus far) -->
  341. <xsl:param name="bestQueryCount" select="0"/> <!-- count of data items in bestQuery: initialize to 0 -->
  342. <xsl:param name="queryIndex" select="1"/> <!-- identifies index of current query in queryList[] -->
  343. <!-- This is a recursive routine that examines current query for items referenced in query item references and
  344. report expressions. If this count is greater than current count, it nominates current query as 'bestQuery',
  345. then examines remaining queries via recursive call. Returns name of 'bestQuery' as passed or nominated.
  346. -->
  347. <xsl:choose>
  348. <xsl:when test="$queryIndex &lt;= count($queryList)"> <!-- list boundary test -->
  349. <!-- Processing query at queryList [ queryIndex ] -->
  350. <!-- name of current query -->
  351. <xsl:variable name="myQueryName" select="string($queryList[$queryIndex])"/>
  352. <!-- count of dangling data items that are found in the current query -->
  353. <xsl:variable name="myQueryCount">
  354. <xsl:call-template name="countQueryItems">
  355. <xsl:with-param name="myQueryItems" select="//v4:BIQuery[@name=$myQueryName]/v4:cube//v4:*[local-name() = 'item' or 'dataItem' = local-name()]"/>
  356. <xsl:with-param name="queryItemRefs" select="$queryItemRefs"/>
  357. <xsl:with-param name="exprItemRefs" select="$exprItemRefs"/>
  358. </xsl:call-template>
  359. </xsl:variable>
  360. <!--DBG- -><xsl:call-template name="countQueryItems"-->
  361. <!--DBG- -><xsl:with-param name="myQueryItems" select="//v4:BIQuery[@name=$myQueryName]/v4:cube//v4:*[local-name() = 'item' or 'dataItem' = local-name()]"/-->
  362. <!--DBG- -><xsl:with-param name="queryItemRefs" select="$queryItemRefs"/-->
  363. <!--DBG- -><xsl:with-param name="exprItemRefs" select="$exprItemRefs"/-->
  364. <!--DBG- -></xsl:call-template-->
  365. <!--DBG- -><xsl:comment> queryList[<xsl:value-of select="$queryIndex"/>] = '<xsl:value-of select="$myQueryName"/>'</xsl:comment-->
  366. <!--DBG- -><xsl:comment> queryCount = <xsl:value-of select="$myQueryCount"/></xsl:comment-->
  367. <xsl:choose>
  368. <xsl:when test="$bestQueryCount &lt; $myQueryCount">
  369. <!-- The current query contains more data items than the last query!
  370. Nominate this query as 'bestQuery', and process next query in list (in case it's even better).
  371. -->
  372. <!--DBG- -><xsl:comment> bestQuery[<xsl:value-of select="$myQueryCount"/>] = '<xsl:value-of select="$myQueryName"/>'</xsl:comment-->
  373. <xsl:call-template name="TestBestQuery">
  374. <xsl:with-param name="bestQuery" select="$myQueryName"/> <!-- Name of this query -->
  375. <xsl:with-param name="bestQueryCount" select="$myQueryCount"/> <!-- new count -->
  376. <xsl:with-param name="queryIndex" select="$queryIndex +1"/> <!-- search next query -->
  377. <xsl:with-param name="queryList" select="$queryList"/>
  378. <xsl:with-param name="queryItemRefs" select="$queryItemRefs"/>
  379. <xsl:with-param name="exprItemRefs" select="$exprItemRefs"/>
  380. </xsl:call-template>
  381. </xsl:when>
  382. <xsl:when test="$queryIndex &lt; count($queryList)">
  383. <!-- There are still queries in the list to process: one of them might be better than current 'bestQuery'.
  384. Process next query in list, using $bestQuery as given
  385. -->
  386. <xsl:call-template name="TestBestQuery">
  387. <xsl:with-param name="queryList" select="$queryList"/>
  388. <xsl:with-param name="queryItemRefs" select="$queryItemRefs"/>
  389. <xsl:with-param name="exprItemRefs" select="$exprItemRefs"/>
  390. <xsl:with-param name="bestQuery" select="$bestQuery"/> <!-- passed query -->
  391. <xsl:with-param name="bestQueryCount" select="$bestQueryCount"/> <!-- passed count -->
  392. <xsl:with-param name="queryIndex" select="$queryIndex +1"/> <!-- search next query -->
  393. </xsl:call-template>
  394. </xsl:when>
  395. <xsl:otherwise>
  396. <!-- No more queries to process: Return name of Best Query as passed -->
  397. <xsl:value-of select="$bestQuery"/>
  398. </xsl:otherwise>
  399. </xsl:choose>
  400. </xsl:when>
  401. <xsl:otherwise>
  402. <!-- When this template was called, all queries had been processed.
  403. Return name of 'Best Query' as nominated.
  404. -->
  405. <xsl:value-of select="$bestQuery"/>
  406. </xsl:otherwise>
  407. </xsl:choose>
  408. </xsl:template>
  409. <!-- === === === === === === === === === === === === === === === -->
  410. <xsl:template name="extractExprItemRefs">
  411. <xsl:param name="exprItemRefs"/> <!-- list of item references extracted from previous expressions -->
  412. <xsl:param name="expressions"/> <!-- expressions with item references -->
  413. <xsl:param name="exprIndex" select="1"/> <!-- start at first expression -->
  414. <!-- This template examines all expressions and extracts query item references from the syntax.
  415. The routine calls itself recursively to iterate through the expressions, passing the current list each time.
  416. -->
  417. <xsl:choose>
  418. <xsl:when test="$exprIndex &lt;= count($expressions)">
  419. <!-- Process current expression -->
  420. <xsl:variable name="myExprItemRefs">
  421. <!-- Extract query item references from current expresion -->
  422. <xsl:call-template name="getExprItemRefs">
  423. <xsl:with-param name="expression" select="$expressions[$exprIndex]"/>
  424. </xsl:call-template>
  425. </xsl:variable>
  426. <!-- Process remaining expressions, including item references from current expression -->
  427. <xsl:call-template name="extractExprItemRefs">
  428. <xsl:with-param name="exprItemRefs" select="concat($exprItemRefs, $myExprItemRefs)"/>
  429. <xsl:with-param name="expressions" select="$expressions"/>
  430. <xsl:with-param name="exprIndex" select="$exprIndex +1"/> <!-- search next expression -->
  431. </xsl:call-template>
  432. </xsl:when>
  433. <xsl:otherwise>
  434. <!-- We've processed all expressions: Return current list -->
  435. <xsl:value-of select="$exprItemRefs"/>
  436. </xsl:otherwise>
  437. </xsl:choose>
  438. </xsl:template>
  439. <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
  440. <xsl:template name="getExprItemRefs">
  441. <xsl:param name="myItemRefs"/> <!-- list of item references extracted from this expression -->
  442. <xsl:param name="expression"/> <!-- current expression text -->
  443. <!-- This is a recursive routine that extracts names of query items referenced in current report expressions. -->
  444. <xsl:choose>
  445. <xsl:when test="contains($expression,'[')">
  446. <!-- Extract first query item reference from current expresion text. -->
  447. <xsl:variable name="qiName" select="substring-after(substring-before($expression, ']'), '[')"/>
  448. <!-- Process remaining expression text, appending above item reference to current list -->
  449. <xsl:call-template name="getExprItemRefs">
  450. <xsl:with-param name="myItemRefs" select="concat($myItemRefs,'[',$qiName,']; ')"/>
  451. <xsl:with-param name="expression" select="substring-after($expression,']')"/> <!-- all expression text after current item reference -->
  452. </xsl:call-template>
  453. </xsl:when>
  454. <xsl:otherwise>
  455. <!-- We've found all item references in current expression: Return current list -->
  456. <xsl:value-of select="$myItemRefs"/>
  457. </xsl:otherwise>
  458. </xsl:choose>
  459. </xsl:template>
  460. <!-- === === === === === === === === === === === === === === === -->
  461. <xsl:template name="countQueryItems">
  462. <xsl:param name="myQueryItems"/> <!-- items in current BI Query -->
  463. <xsl:param name="queryItemRefs"/> <!-- dangling data items -->
  464. <xsl:param name="exprItemRefs"/> <!-- dangling data items in expressions -->
  465. <xsl:param name="queryItemCount" select="0"/> <!-- current item count: initialized at zero -->
  466. <xsl:param name="queryItemIndex" select="1"/> <!-- current item count: initialized at zero -->
  467. <!-- This template counts all of the items in the query that match an explicit query item reference or a
  468. reference from a report expression.
  469. The routine calls itself recursively to iterate through the items.
  470. -->
  471. <xsl:choose>
  472. <xsl:when test="$queryItemIndex &lt;= count($myQueryItems)">
  473. <!-- Still processing items in list; Process current item. -->
  474. <xsl:variable name="myItem" select="$myQueryItems[$queryItemIndex]"/>
  475. <xsl:variable name="myItemName">
  476. <xsl:choose>
  477. <xsl:when test="$myItem/@name"><xsl:value-of select="$myItem/@name"/></xsl:when>
  478. <xsl:when test="$myItem/@alias"><xsl:value-of select="$myItem/@alias"/></xsl:when>
  479. <xsl:when test="$myItem/@refItem"><xsl:value-of select="$myItem/@refItem"/></xsl:when>
  480. <xsl:otherwise></xsl:otherwise>
  481. </xsl:choose>
  482. </xsl:variable>
  483. <xsl:variable name="myCount">
  484. <xsl:choose>
  485. <xsl:when test="$myItemName = $queryItemRefs">1</xsl:when>
  486. <xsl:when test="contains($exprItemRefs, concat('[',$myItemName,']; '))">1</xsl:when>
  487. <xsl:otherwise>0</xsl:otherwise>
  488. </xsl:choose>
  489. </xsl:variable>
  490. <!--DBG- -><xsl:comment> queryItem[<xsl:value-of select="$queryItemIndex"/>] = '<xsl:value-of select="$myItemName"/>' (<xsl:value-of select="$myCount"/>)</xsl:comment-->
  491. <!-- Process next item in list -->
  492. <xsl:call-template name="countQueryItems">
  493. <xsl:with-param name="myQueryItems" select="$myQueryItems"/>
  494. <xsl:with-param name="queryItemRefs" select="$queryItemRefs"/>
  495. <xsl:with-param name="exprItemRefs" select="$exprItemRefs"/>
  496. <xsl:with-param name="queryItemCount" select="$queryItemCount + $myCount"/>
  497. <xsl:with-param name="queryItemIndex" select="$queryItemIndex +1"/>
  498. </xsl:call-template>
  499. </xsl:when>
  500. <xsl:otherwise>
  501. <!-- All query items have been processed; Return current count -->
  502. <xsl:value-of select="$queryItemCount"/>
  503. </xsl:otherwise>
  504. </xsl:choose>
  505. </xsl:template>
  506. <!-- =============================================================================== -->
  507. </xsl:stylesheet>