pagination - How to use XSLT to create pages of varying sizes for an XML file? -
i have large xml file of format:
<data jsxid="jsxroot" casenumber="59878"> <record jsxid="1" ponumber="13-192208" manu="biotronik" catnumber="101" total="0" /> <record jsxid="2" ponumber="13-192208" manu="biotronik" catnumber="102" total="0" /> <record jsxid="3" ponumber="13-192208" manu="biotronik total" catnumber="" total="1" /> <record jsxid="4" ponumber="13-192211" manu="biotronik" catnumber="103" total="0" /> <record jsxid="5" ponumber="13-192211" manu="biotronik total" catnumber="" total="1"/>
i want paginate groups of 25 or less, , each page must end on total line (@total="1").
i got far inserting static page number using following xsl, cuts off in middle of ponumber group total on next page:
<xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:param name="pagesize" select="25" /> <xsl:template match="data"> <data> <xsl:for-each select="@*"> <xsl:copy-of select="." /> </xsl:for-each> <xsl:apply-templates mode="page" select="record[position() mod $pagesize = 1]" /> </data> </xsl:template> <xsl:template match="record" mode="page"> <record jsxid="{position()}" > <xsl:apply-templates select=". | following-sibling::record[position() < $pagesize]" /> </record> </xsl:template> <xsl:template match="record"> <xsl:copy-of select="." /> </xsl:template>
any ideas on how make sure last record on each page total?
edit: wanted clarify doing stylesheet posted. inserts placeholder page (jsxid = n) every ($pagesize) records. if pagesize = 5 dataset similar 1 posted, output is:
<data jsxid="jsxroot" casenumber="59878"> <record jsxid="1"> <record jsxid="1" ponumber="13-192208" manufacturer="biotronik" catalognumber="101" total="0" /> <record jsxid="2" ponumber="13-192208" manufacturer="biotronik" catalognumber="102" total="0" /> <record jsxid="3" ponumber="13-192208" manufacturer="biotronik total" catalognumber="" total="1" /> <record jsxid="4" ponumber="13-192211" manufacturer="biotronik" catalognumber="103" total="0" /> <record jsxid="5" ponumber="13-192211" manufacturer="biotronik total" catalognumber="" total="1"/> <record jsxid="2"> <record jsxid="6" ponumber="13-192208" manufacturer="biotronik" catalognumber="101" total="0" /> <record jsxid="7" ponumber="13-192208" manufacturer="biotronik" catalognumber="102" total="0" />
i'm displaying data in matrix in general interface , using jsxid iterate between "pages."
thanks.
i got far inserting static page number using following xsl
i don't see anywhere in stylesheet posted. assuming pagination mean assigning page number each record, try:
xslt 1.0
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:param name="pagesize" select="25" /> <xsl:key name="record" match="record" use="@ponumber" /> <xsl:template match="/data"> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="record[@total=1]"/> <xsl:with-param name="page" select="1"/> <xsl:with-param name="existing-lines" select="0"/> </xsl:call-template> </xsl:copy> </xsl:template> <xsl:template name="paginate"> <xsl:param name="orders" /> <xsl:param name="page"/> <xsl:param name="existing-lines"/> <xsl:param name="current-order-records" select="key('record', $orders[1]/@ponumber)"/> <xsl:param name="added-lines" select="count($current-order-records)"/> <xsl:choose> <xsl:when test="$existing-lines + $added-lines > $pagesize"> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="$orders"/> <xsl:with-param name="page" select="$page + 1"/> <xsl:with-param name="existing-lines" select="0"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:for-each select="$current-order-records"> <record page="{$page}"> <xsl:copy-of select="@*"/> </record> </xsl:for-each> <xsl:if test="count($orders) > 1"> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="$orders[position() > 1]"/> <xsl:with-param name="page" select="$page"/> <xsl:with-param name="existing-lines" select="$existing-lines + $added-lines "/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
your input small test this, ... note crash if ponumber has more 25 records.
edit:
creating container element each page considerably more difficult: pre-processing pass required. try:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:param name="pagesize" select="25" /> <xsl:key name="record" match="record" use="@ponumber" /> <xsl:variable name="root" select="/" /> <xsl:template match="/data"> <!-- first-pass --> <xsl:variable name="index"> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="record[@total=1]"/> <xsl:with-param name="page" select="1"/> <xsl:with-param name="existing-lines" select="0"/> </xsl:call-template> </xsl:variable> <xsl:variable name="index-entry" select="exsl:node-set($index)/entry" /> <!-- output --> <xsl:copy> <xsl:copy-of select="@*" /> <xsl:for-each select="$index-entry[@page-start='true']"> <record jsxid="{@page}"> <xsl:variable name="ponumbers" select="$index-entry[@page=current()/@page]/@ponumber" /> <xsl:for-each select="$root"> <xsl:copy-of select="key('record', $ponumbers)"/> </xsl:for-each> </record> </xsl:for-each> </xsl:copy> </xsl:template> <xsl:template name="paginate"> <xsl:param name="orders" /> <xsl:param name="page"/> <xsl:param name="existing-lines"/> <xsl:param name="current-order-records" select="key('record', $orders[1]/@ponumber)"/> <xsl:param name="added-lines" select="count($current-order-records)"/> <xsl:choose> <xsl:when test="$existing-lines + $added-lines > $pagesize"> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="$orders"/> <xsl:with-param name="page" select="$page + 1"/> <xsl:with-param name="existing-lines" select="0"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <entry page="{$page}" page-start="{$existing-lines = 0}"> <xsl:copy-of select="$orders[1]/@*"/> </entry> <xsl:if test="count($orders) > 1"> <xsl:call-template name="paginate"> <xsl:with-param name="orders" select="$orders[position() > 1]"/> <xsl:with-param name="page" select="$page"/> <xsl:with-param name="existing-lines" select="$existing-lines + $added-lines "/> </xsl:call-template> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
edit 2:
to calculate minimum page size required largest po, add @ top level of stylesheet (outside of template):
<xsl:variable name="largestpo"> <xsl:for-each select="/data/record[@total = 1]"> <xsl:sort select="count(key('record', @ponumber))" data-type="number" order="descending"/> <xsl:if test="position()=1"> <xsl:value-of select="count(key('record', @ponumber))" /> </xsl:if> </xsl:for-each> </xsl:variable>
now need compare default page size , pick larger of two.
Comments
Post a Comment