Html 按列跨度的XSLT同级递归,可以检测后续列区域是否被占用
我有一个部分工作的XSLT,它根据列分隔符按列对元素进行分组。“我的元素”显示在一列中,直到遇到一个Html 按列跨度的XSLT同级递归,可以检测后续列区域是否被占用,html,xml,twitter-bootstrap,xslt,muenchian-grouping,Html,Xml,Twitter Bootstrap,Xslt,Muenchian Grouping,我有一个部分工作的XSLT,它根据列分隔符按列对元素进行分组。“我的元素”显示在一列中,直到遇到一个,这将使后续项目呈现在右侧的新列中 现在,我想扩展这个XSLT,以实现基于项目宽度的列跨度的概念,因此我遵循了本文的示例实现。此外,如果由于前一个元素的宽度跨度,下一列中已占用一个区域,则ColumnBreak后面的后续元素应显示在已占用区域的下方 XML: <?xml version="1.0" encoding="utf-8" ?> <Group> <It
,这将使后续项目呈现在右侧的新列中
现在,我想扩展这个XSLT,以实现基于项目宽度的列跨度的概念,因此我遵循了本文的示例实现。此外,如果由于前一个元素的宽度跨度,下一列中已占用一个区域,则ColumnBreak
后面的后续元素应显示在已占用区域的下方
XML:
<?xml version="1.0" encoding="utf-8" ?>
<Group>
<Items>
<Item>
<Display>Item 1</Display>
</Item>
<Item>
<Display>Item 2</Display>
<Width>2</Width>
</Item>
<Item>
<Display>Item 3</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 4</Display>
</Item>
<Item>
<Display>Item 5</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 6</Display>
</Item>
<Item>
<Display>Item 7</Display>
</Item>
</Items>
</Group>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
exclude-result-prefixes="msxsl xsi">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Group">
<xsl:apply-templates select="Items"/>
</xsl:template>
<xsl:key name="cell-by-row" match="cell" use="@row" />
<xsl:key name="cell-by-col" match="cell" use="concat(@row, '|', @col)" />
<xsl:template match="Items">
<div>
<xsl:variable name="cells">
<xsl:apply-templates select="*[1]" mode="item-sibling">
<xsl:with-param name="row" select="1"/>
<xsl:with-param name="col" select="1"/>
<xsl:with-param name="index" select="1"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name="generate-rows">
<xsl:with-param name="cells" select="$cells" />
<xsl:with-param name="current-row" select="1"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="cells" />
<xsl:param name="current-row" />
<xsl:param name="last-row" />
<xsl:for-each select="exsl:node-set($cells)/cell[count(. | key('cell-by-row', @row)[1]) = 1]">
<xsl:for-each select="key('cell-by-row', @row)[count(. | key('cell-by-col', concat(@row, '|', @col))[1]) = 1]">
<xsl:for-each select="key('cell-by-col', concat(@row, '|', @col))">
<xsl:if test="not(@empty)">
<div row="{@row}" col="{@col}" index="{@index}" width="{@width}">
<xsl:apply-templates select="." mode="item">
</xsl:apply-templates>
</div>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="*" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells" select="some-dummy-node-to-make-this-a-node"/>
<xsl:variable name="width">
<xsl:call-template name="width-template" />
</xsl:variable>
<xsl:variable name="colliding-cell" select="exsl:node-set($previous-cells)/cell[@row = $row and @col < $col and @index > $index and @width + @col > $col]" />
<xsl:choose>
<xsl:when test="$colliding-cell">
<xsl:apply-templates select="self::node()" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$colliding-cell/@index + 1"/>
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="current-cell">
<cell row="{$row}" col="{$col}" index="{$index}" width="{$width}">
<xsl:copy-of select="exsl:node-set(.)"/>
</cell>
</xsl:variable>
<xsl:variable name="new-cells">
<xsl:copy-of select="$previous-cells"/>
<xsl:copy-of select="$current-cell"/>
</xsl:variable>
<xsl:copy-of select="$current-cell"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="previous-cells" select="$new-cells"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ColumnBreak" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col + 1"/>
<xsl:with-param name="index" select="1" />
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="width-template">
<xsl:choose>
<xsl:when test="Width">
<xsl:value-of select="Width" />
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Item" mode="item">
<xsl:value-of select="Display" />
</xsl:template>
</xsl:stylesheet>
项目1
项目2
2.
项目3
项目4
项目5
项目6
项目7
XSLT:
<?xml version="1.0" encoding="utf-8" ?>
<Group>
<Items>
<Item>
<Display>Item 1</Display>
</Item>
<Item>
<Display>Item 2</Display>
<Width>2</Width>
</Item>
<Item>
<Display>Item 3</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 4</Display>
</Item>
<Item>
<Display>Item 5</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 6</Display>
</Item>
<Item>
<Display>Item 7</Display>
</Item>
</Items>
</Group>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
exclude-result-prefixes="msxsl xsi">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Group">
<xsl:apply-templates select="Items"/>
</xsl:template>
<xsl:key name="cell-by-row" match="cell" use="@row" />
<xsl:key name="cell-by-col" match="cell" use="concat(@row, '|', @col)" />
<xsl:template match="Items">
<div>
<xsl:variable name="cells">
<xsl:apply-templates select="*[1]" mode="item-sibling">
<xsl:with-param name="row" select="1"/>
<xsl:with-param name="col" select="1"/>
<xsl:with-param name="index" select="1"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name="generate-rows">
<xsl:with-param name="cells" select="$cells" />
<xsl:with-param name="current-row" select="1"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="cells" />
<xsl:param name="current-row" />
<xsl:param name="last-row" />
<xsl:for-each select="exsl:node-set($cells)/cell[count(. | key('cell-by-row', @row)[1]) = 1]">
<xsl:for-each select="key('cell-by-row', @row)[count(. | key('cell-by-col', concat(@row, '|', @col))[1]) = 1]">
<xsl:for-each select="key('cell-by-col', concat(@row, '|', @col))">
<xsl:if test="not(@empty)">
<div row="{@row}" col="{@col}" index="{@index}" width="{@width}">
<xsl:apply-templates select="." mode="item">
</xsl:apply-templates>
</div>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="*" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells" select="some-dummy-node-to-make-this-a-node"/>
<xsl:variable name="width">
<xsl:call-template name="width-template" />
</xsl:variable>
<xsl:variable name="colliding-cell" select="exsl:node-set($previous-cells)/cell[@row = $row and @col < $col and @index > $index and @width + @col > $col]" />
<xsl:choose>
<xsl:when test="$colliding-cell">
<xsl:apply-templates select="self::node()" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$colliding-cell/@index + 1"/>
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="current-cell">
<cell row="{$row}" col="{$col}" index="{$index}" width="{$width}">
<xsl:copy-of select="exsl:node-set(.)"/>
</cell>
</xsl:variable>
<xsl:variable name="new-cells">
<xsl:copy-of select="$previous-cells"/>
<xsl:copy-of select="$current-cell"/>
</xsl:variable>
<xsl:copy-of select="$current-cell"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="previous-cells" select="$new-cells"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ColumnBreak" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col + 1"/>
<xsl:with-param name="index" select="1" />
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="width-template">
<xsl:choose>
<xsl:when test="Width">
<xsl:value-of select="Width" />
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Item" mode="item">
<xsl:value-of select="Display" />
</xsl:template>
</xsl:stylesheet>
1.
预期结果*:
<?xml version="1.0" encoding="utf-8" ?>
<Group>
<Items>
<Item>
<Display>Item 1</Display>
</Item>
<Item>
<Display>Item 2</Display>
<Width>2</Width>
</Item>
<Item>
<Display>Item 3</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 4</Display>
</Item>
<Item>
<Display>Item 5</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 6</Display>
</Item>
<Item>
<Display>Item 7</Display>
</Item>
</Items>
</Group>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
exclude-result-prefixes="msxsl xsi">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Group">
<xsl:apply-templates select="Items"/>
</xsl:template>
<xsl:key name="cell-by-row" match="cell" use="@row" />
<xsl:key name="cell-by-col" match="cell" use="concat(@row, '|', @col)" />
<xsl:template match="Items">
<div>
<xsl:variable name="cells">
<xsl:apply-templates select="*[1]" mode="item-sibling">
<xsl:with-param name="row" select="1"/>
<xsl:with-param name="col" select="1"/>
<xsl:with-param name="index" select="1"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name="generate-rows">
<xsl:with-param name="cells" select="$cells" />
<xsl:with-param name="current-row" select="1"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="cells" />
<xsl:param name="current-row" />
<xsl:param name="last-row" />
<xsl:for-each select="exsl:node-set($cells)/cell[count(. | key('cell-by-row', @row)[1]) = 1]">
<xsl:for-each select="key('cell-by-row', @row)[count(. | key('cell-by-col', concat(@row, '|', @col))[1]) = 1]">
<xsl:for-each select="key('cell-by-col', concat(@row, '|', @col))">
<xsl:if test="not(@empty)">
<div row="{@row}" col="{@col}" index="{@index}" width="{@width}">
<xsl:apply-templates select="." mode="item">
</xsl:apply-templates>
</div>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="*" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells" select="some-dummy-node-to-make-this-a-node"/>
<xsl:variable name="width">
<xsl:call-template name="width-template" />
</xsl:variable>
<xsl:variable name="colliding-cell" select="exsl:node-set($previous-cells)/cell[@row = $row and @col < $col and @index > $index and @width + @col > $col]" />
<xsl:choose>
<xsl:when test="$colliding-cell">
<xsl:apply-templates select="self::node()" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$colliding-cell/@index + 1"/>
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="current-cell">
<cell row="{$row}" col="{$col}" index="{$index}" width="{$width}">
<xsl:copy-of select="exsl:node-set(.)"/>
</cell>
</xsl:variable>
<xsl:variable name="new-cells">
<xsl:copy-of select="$previous-cells"/>
<xsl:copy-of select="$current-cell"/>
</xsl:variable>
<xsl:copy-of select="$current-cell"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="previous-cells" select="$new-cells"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ColumnBreak" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col + 1"/>
<xsl:with-param name="index" select="1" />
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="width-template">
<xsl:choose>
<xsl:when test="Width">
<xsl:value-of select="Width" />
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Item" mode="item">
<xsl:value-of select="Display" />
</xsl:template>
</xsl:stylesheet>
场景1:项目2宽度=2
场景2:项目2宽度=2,项目4宽度=2
*为了便于说明,我在场景截图中使用了HTML表格,但基本上项目不需要按行精确对齐,因为我的元素可能因高度而异。最终目标是将它们分组为列
电流输出:
<?xml version="1.0" encoding="utf-8" ?>
<Group>
<Items>
<Item>
<Display>Item 1</Display>
</Item>
<Item>
<Display>Item 2</Display>
<Width>2</Width>
</Item>
<Item>
<Display>Item 3</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 4</Display>
</Item>
<Item>
<Display>Item 5</Display>
</Item>
<ColumnBreak />
<Item>
<Display>Item 6</Display>
</Item>
<Item>
<Display>Item 7</Display>
</Item>
</Items>
</Group>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:exsl="http://exslt.org/common" extension-element-prefixes="exsl"
exclude-result-prefixes="msxsl xsi">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Group">
<xsl:apply-templates select="Items"/>
</xsl:template>
<xsl:key name="cell-by-row" match="cell" use="@row" />
<xsl:key name="cell-by-col" match="cell" use="concat(@row, '|', @col)" />
<xsl:template match="Items">
<div>
<xsl:variable name="cells">
<xsl:apply-templates select="*[1]" mode="item-sibling">
<xsl:with-param name="row" select="1"/>
<xsl:with-param name="col" select="1"/>
<xsl:with-param name="index" select="1"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:call-template name="generate-rows">
<xsl:with-param name="cells" select="$cells" />
<xsl:with-param name="current-row" select="1"/>
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="cells" />
<xsl:param name="current-row" />
<xsl:param name="last-row" />
<xsl:for-each select="exsl:node-set($cells)/cell[count(. | key('cell-by-row', @row)[1]) = 1]">
<xsl:for-each select="key('cell-by-row', @row)[count(. | key('cell-by-col', concat(@row, '|', @col))[1]) = 1]">
<xsl:for-each select="key('cell-by-col', concat(@row, '|', @col))">
<xsl:if test="not(@empty)">
<div row="{@row}" col="{@col}" index="{@index}" width="{@width}">
<xsl:apply-templates select="." mode="item">
</xsl:apply-templates>
</div>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="*" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells" select="some-dummy-node-to-make-this-a-node"/>
<xsl:variable name="width">
<xsl:call-template name="width-template" />
</xsl:variable>
<xsl:variable name="colliding-cell" select="exsl:node-set($previous-cells)/cell[@row = $row and @col < $col and @index > $index and @width + @col > $col]" />
<xsl:choose>
<xsl:when test="$colliding-cell">
<xsl:apply-templates select="self::node()" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$colliding-cell/@index + 1"/>
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="current-cell">
<cell row="{$row}" col="{$col}" index="{$index}" width="{$width}">
<xsl:copy-of select="exsl:node-set(.)"/>
</cell>
</xsl:variable>
<xsl:variable name="new-cells">
<xsl:copy-of select="$previous-cells"/>
<xsl:copy-of select="$current-cell"/>
</xsl:variable>
<xsl:copy-of select="$current-cell"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="previous-cells" select="$new-cells"/>
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ColumnBreak" mode="item-sibling">
<xsl:param name="row"/>
<xsl:param name="col"/>
<xsl:param name="index"/>
<xsl:param name="previous-cells"/>
<xsl:apply-templates select="following-sibling::*[1]" mode="item-sibling">
<xsl:with-param name="row" select="$row"/>
<xsl:with-param name="col" select="$col + 1"/>
<xsl:with-param name="index" select="1" />
<xsl:with-param name="previous-cells" select="$previous-cells"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template name="width-template">
<xsl:choose>
<xsl:when test="Width">
<xsl:value-of select="Width" />
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="Item" mode="item">
<xsl:value-of select="Display" />
</xsl:template>
</xsl:stylesheet>
我当前的XSLT生成一个原始矩阵,它显示元素的列分配及其相应的宽度。如何将此矩阵转换为HTML
布局,使其看起来与上面的预期结果类似
我的XSLT小提琴:
谢谢大家! 那么所有的
div
都属于相同的row=“1”
?div
s中的内容或任何数据在哪里?你有没有研究过CSS网格布局(如果你的目标是现代布局引擎)?我正在考虑引导,但我仍然不知道如何将我的原始布局转换为网格布局。在本例中,我的元素都属于row=1,但是可以有多行(具有复杂的列),尽管我在这里没有提到。我更新了小提琴以显示内容。因此所有div
s都属于同一row=“1”
?div
s中的内容或任何数据在哪里?你有没有研究过CSS网格布局(如果你的目标是现代布局引擎)?我正在考虑引导,但我仍然不知道如何将我的原始布局转换为网格布局。在本例中,我的元素都属于row=1,但是可以有多行(具有复杂的列),尽管我在这里没有提到。我更新了小提琴以显示内容。