Reputation: 591
I plan to apply a template recursively to scan through all the items (rows and columns) in the input XML.
Here is the input xml:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1" colspan="3">
</item>
<item row="1" column="3">
</item>
<item row="0" column="1">
</item>
</layout>
</ui>
Here is my code:
<!-- ********************** Main Program ********************** -->
<xsl:variable name="maxR" select="xs:integer(max(layout/item/@row))" as="xs:integer" />
<xsl:variable name="maxC" select="xs:integer(max(layout/item/@column))" as="xs:integer" />
(<xsl:value-of select="$maxR"/>, <xsl:value-of select="$maxC"/>)
<ul>
<xsl:apply-templates select="layout/item">
<xsl:with-param name="curR" select="0"/>
<xsl:with-param name="curC" select="0"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:apply-templates>
</ul>
<!-- ********************** Template ********************** -->
<xsl:template name="grpBxRC" match="layout/item">
<xsl:param name="curR" as="xs:integer"/>
<xsl:param name="curC" as="xs:integer"/>
<xsl:param name="maxR" as="xs:integer"/>
<xsl:param name="maxC" as="xs:integer"/>
[<xsl:value-of select="$curR"/>, <xsl:value-of select="$curC"/>]
<xsl:if test="$maxC > $curC">
<xsl:apply-templates select="layout/item">
<xsl:with-param name="curR" select="$curR"/>
<xsl:with-param name="curC" select="$curC + 1"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
When I run it, I got output as:
(1, 3)
[0, 0] [0, 0] [0, 0] [0, 0] [0, 0] [0, 0] [0, 0] [0, 0]
(1,3) is correct for maxR and maxC. However, I expect
(1,3)
[0,0] [0,1] [0,2]
I don't what's wrong? It seems $curC + 1 did not work?
Upvotes: 0
Views: 56
Reputation: 1695
Seems you have missed some lines to copy your xslt code above. Considering the below as your current xslt code.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:variable name="maxR" select="xs:integer(max(//layout/item/@row))" as="xs:integer"/>
<xsl:variable name="maxC" select="xs:integer(max(//layout/item/@column))" as="xs:integer"/>
<xsl:template match="/ui">
(<xsl:value-of select="$maxR"/>,<xsl:value-of select="$maxC"/>)
<ul>
<xsl:apply-templates select="layout/item">
<xsl:with-param name="curR" select="0"/>
<xsl:with-param name="curC" select="0"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:apply-templates>
</ul>
</xsl:template>
<!-- ********************** Template ********************** -->
<xsl:template name="grpBxRC" match="layout/item">
<xsl:param name="curR" as="xs:integer"/>
<xsl:param name="curC" as="xs:integer"/>
<xsl:param name="maxR" as="xs:integer"/>
<xsl:param name="maxC" as="xs:integer"/>
[<xsl:value-of select="$curR"/>,<xsl:value-of select="$curC"/>]
<xsl:if test="$maxC > $curC">
<xsl:apply-templates select="layout/item">
<xsl:with-param name="curR" select="$curR"/>
<xsl:with-param name="curC" select="$curC + 1"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
From your expected output, it looks like you're trying to print matrix elements or table cells from maximum no. of row and column you get i.e. (1,3)
In your xslt, the
<xsl:apply-templates select="layout/item">
call in<xsl:template name="grpBxRC" match="layout/item">
template doesn't work because it couldn't match the node without any reference of it's parent node. It can work by changing it to/ui/layout/item
OR//layout/item
, although it won't give the required output.You could also use
<xsl:call-template>
here instead of<xsl:apply-templates>
as below, BUT that will call the whole template<xsl:template name="grpBxRC" match="layout/item">
as many times as node<item>
appears in<layout>
due to use of apply-templates
<!-- ********************** Template ********************** -->
<xsl:template name="grpBxRC" match="layout/item">
<xsl:param name="curR" as="xs:integer"/>
<xsl:param name="curC" as="xs:integer"/>
<xsl:param name="maxR" as="xs:integer"/>
<xsl:param name="maxC" as="xs:integer"/>
<xsl:if test="$maxC > $curC">
[<xsl:value-of select="$curR"/>,<xsl:value-of select="$curC"/>]
<xsl:call-template name="grpBxRC">
<xsl:with-param name="curR" select="$curR"/>
<xsl:with-param name="curC" select="$curC + 1"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
In order to achieve your expected result, one way could be as below if you have specific requirements to stick to having dynamic columns:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:variable name="maxR" select="xs:integer(max(//layout/item/@row))" as="xs:integer"/>
<xsl:variable name="maxC" select="xs:integer(max(//layout/item/@column))" as="xs:integer"/>
<xsl:template match="/ui">
(<xsl:value-of select="$maxR"/>,<xsl:value-of select="$maxC"/>)
<xsl:call-template name="grpBxRC">
<xsl:with-param name="node" select="layout/item"/>
<xsl:with-param name="curR" select="0"/>
<xsl:with-param name="curC" select="0"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="grpBxRC">
<xsl:param name="node"/>
<xsl:param name="curR" as="xs:integer"/>
<xsl:param name="curC" as="xs:integer"/>
<xsl:param name="maxR" as="xs:integer"/>
<xsl:param name="maxC" as="xs:integer"/>
<xsl:if test="$maxC > $curC">
[<xsl:value-of select="$curR"/>,<xsl:value-of select="$curC"/>]
<xsl:call-template name="grpBxRC">
<xsl:with-param name="node"/>
<xsl:with-param name="curR" select="$curR"/>
<xsl:with-param name="curC" select="$curC + 1"/>
<xsl:with-param name="maxR" select="$maxR"/>
<xsl:with-param name="maxC" select="$maxC"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
But, if you want both row and column to be increased dynamically, you could go with following solution:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:variable name="maxR" select="xs:integer(max(//layout/item/@row))" as="xs:integer"/>
<xsl:variable name="maxC" select="xs:integer(max(//layout/item/@column))" as="xs:integer"/>
<xsl:template match="/ui">
(<xsl:value-of select="$maxR"/>,<xsl:value-of select="$maxC"/>)
<xsl:call-template name="iterate-row">
<xsl:with-param name="row" select="0"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="iterate-row">
<xsl:param name="row"/>
<xsl:if test="$maxR > $row">
<xsl:call-template name="iterate-column">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="0"/>
</xsl:call-template>
<xsl:call-template name="iterate-row">
<xsl:with-param name="row" select="$row + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="iterate-column">
<xsl:param name="col"/>
<xsl:param name="row"/>
<xsl:if test="$maxC > $col ">
[<xsl:value-of select="$row"/>,<xsl:value-of select="$col"/>]
<xsl:call-template name="iterate-column">
<xsl:with-param name="col" select="$col + 1"/>
<xsl:with-param name="row" select="$row"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1