Ruby 如何使用xslt应用两个模板并按大小和使用的模板对结果进行分组
我正在尝试解析一个XML并生成一个可以用于打印的HTML XML中元素的内容像卡片一样呈现,正面和背面都有信息。一页可以放八张卡片。 为了使HTML/CSS世界中的定位工作更轻松,我想按如下方式预先安排XSLT输出: 对于输入中的16个元素,我希望先获得前8个元素的正面输出,然后以不同的顺序获得前8个元素的背面输出,以便在使用双面打印时与相应的正面匹配,然后获得下8个元素的正面输出,以此类推 背面的顺序是这样的:前半部分按相反顺序,后半部分按相反顺序。例如背面卡片4、3、2、1、8、7、6、5 或者对于以下输入(为了简单起见,我仅使用每页4张卡片作为示例):Ruby 如何使用xslt应用两个模板并按大小和使用的模板对结果进行分组,ruby,xml,xslt,xslt-1.0,nokogiri,Ruby,Xml,Xslt,Xslt 1.0,Nokogiri,我正在尝试解析一个XML并生成一个可以用于打印的HTML XML中元素的内容像卡片一样呈现,正面和背面都有信息。一页可以放八张卡片。 为了使HTML/CSS世界中的定位工作更轻松,我想按如下方式预先安排XSLT输出: 对于输入中的16个元素,我希望先获得前8个元素的正面输出,然后以不同的顺序获得前8个元素的背面输出,以便在使用双面打印时与相应的正面匹配,然后获得下8个元素的正面输出,以此类推 背面的顺序是这样的:前半部分按相反顺序,后半部分按相反顺序。例如背面卡片4、3、2、1、8、7、6、5
首先是前线
先到后
前线第二名
倒数第二
第三个是前线
倒数第三
第四是前线
倒数第四
第五名为前线
后面第五个
我希望获得以下输出:
<html><body>
<div>
<div class="card1 front">First for the front</div>
<div class="card2 front">Second for the front</div>
<div class="card3 front">Third for the front</div>
<div class="card4 front">Fourth for the front</div>
</div>
<div>
<div class="card2 back">Second to the back</div>
<div class="card1 back">First to the back</div>
<div class="card4 back">Fourth to the back</div>
<div class="card3 back">Third to the back</div>
</div>
<div>
<div class="card1 front">Fifth for the front</div>
</div>
<div>
<div class="card1 back">Fifth to the back</div>
</div>
</body></html>
首先是前线
前线第二名
第三个是前线
第四是前线
倒数第二
先到后
倒数第四
倒数第三
第五名为前线
后面第五个
我想在下一个匹配和模式中处理元素两次,但我不知道如何将其与我想应用的排序/分组相结合
我真的很感谢有一个指向正确方向的指针。此XSLT 1.0转换实现了所需的结构:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="UTF-8" indent="yes" />
<xsl:template match="/cards">
<html>
<body>
<xsl:for-each select="card[position() mod 4 = 1]">
<xsl:variable name="thisPage" select="
. | following-sibling::card[position() < 4]
" />
<div class="front">
<xsl:apply-templates select="$thisPage/question" />
</div>
<div class="back">
<xsl:apply-templates select="$thisPage/answer">
<xsl:sort select="substring('2143', position(), 1)" data-type="number" />
</xsl:apply-templates>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template match="card/*">
<div class="card">
<xsl:value-of select="normalize-space()" />
</div>
</xsl:template>
</xsl:transform>
也就是说,通过组合CSS中的
position:absolute
和nth child
,您还可以在背面实现独立于源代码顺序的整个定位。这样一来,XSLT中的特殊排序就没有必要了。让我们把它变成通用的-我们希望每页都有$rows
行$cols
卡片,并且在答案端,每行都需要按相反的顺序打印
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:param name="rows" select="2" />
<xsl:param name="cols" select="2" />
<xsl:variable name="pageSize" select="$rows * $cols" />
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="cards/card[position() mod $pageSize = 1]" />
</body>
</html>
</xsl:template>
<xsl:template match="card">
<!-- fronts -->
<div>
<xsl:call-template name="printRows">
<xsl:with-param name="element" select="1"/>
<xsl:with-param name="order" select="'ascending'" />
</xsl:call-template>
</div>
<!-- backs -->
<div>
<xsl:call-template name="printRows">
<xsl:with-param name="element" select="2"/>
<xsl:with-param name="order" select="'descending'" />
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="printRows">
<xsl:param name="element" />
<xsl:param name="order" />
<xsl:variable name="thePage"
select=". | following-sibling::card[position() < $pageSize]" />
<!-- split into rows -->
<xsl:for-each select="$thePage[position() mod $cols = 1]">
<xsl:variable name="theRow"
select=". | following-sibling::card[position() < $cols]" />
<!-- and process each row in appropriate order -->
<xsl:apply-templates select="$theRow/*[$element]">
<xsl:sort select="position()" order="{$order}" data-type="number" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:template>
<xsl:template match="question">
<div class="card{(count(../preceding-sibling::card) mod $pageSize) + 1} front">
<xsl:value-of select="." />
</div>
</xsl:template>
<xsl:template match="answer">
<div class="card{(count(../preceding-sibling::card) mod $pageSize) + 1} back">
<xsl:value-of select="." />
</div>
</xsl:template>
</xsl:stylesheet>
其中emptyDivs
模板
<xsl:template name="emptyDivs">
<xsl:param name="num"/>
<xsl:if test="$num > 0">
<div class="padding back" />
<xsl:call-template name="emptyDivs">
<xsl:with-param name="num" select="$num - 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
这将为两行乘两列的页面生成以下输出:
<html>
<body>
<div>
<div class="card1 front">First for the front</div>
<div class="card2 front">Second for the front</div>
<div class="card3 front">Third for the front</div>
<div class="card4 front">Fourth for the front</div>
</div>
<div>
<div class="card2 back">Second to the back</div>
<div class="card1 back">First to the back</div>
<div class="card4 back">Fourth to the back</div>
<div class="card3 back">Third to the back</div>
</div>
<div>
<div class="card1 front">Fifth for the front</div>
</div>
<div>
<div class="padding back"></div>
<div class="card1 back">Fifth to the back</div>
</div>
</body>
</html>
首先是前线
前线第二名
第三个是前线
第四是前线
倒数第二
先到后
倒数第四
倒数第三
第五名为前线
后面第五个
或两行三列的以下内容:
<html>
<body>
<div>
<div class="card1 front">First for the front</div>
<div class="card2 front">Second for the front</div>
<div class="card3 front">Third for the front</div>
<div class="card4 front">Fourth for the front</div>
<div class="card5 front">Fifth for the front</div>
</div>
<div>
<div class="card3 back">Third to the back</div>
<div class="card2 back">Second to the back</div>
<div class="card1 back">First to the back</div>
<div class="padding back"></div>
<div class="card5 back">Fifth to the back</div>
<div class="card4 back">Fourth to the back</div>
</div>
</body>
</html>
首先是前线
前线第二名
第三个是前线
第四是前线
第五名为前线
倒数第三
倒数第二
先到后
后面第五个
倒数第四
您能使用XSLT 2.0吗?“首先是前8个元素的正面输出,然后是前8个元素的背面输出,顺序相反,”我在您的示例输出中看不到这一点。为什么顺序是2、1、4、3?我使用ruby和nokogiri库进行xslt处理。因此,只有XSLT1.0或者如果您知道另一个适用于ruby的优秀XSLT2.0库,我才可以使用它。XSLT1.0也可以使用它。但您需要澄清后端排序背后的逻辑。据我所知,Ruby没有XSLT2.0库,Nokogiri是最好的选择。我已经为你重新标记了这个问题。
<html>
<body>
<div>
<div class="card1 front">First for the front</div>
<div class="card2 front">Second for the front</div>
<div class="card3 front">Third for the front</div>
<div class="card4 front">Fourth for the front</div>
</div>
<div>
<div class="card2 back">Second to the back</div>
<div class="card1 back">First to the back</div>
<div class="card4 back">Fourth to the back</div>
<div class="card3 back">Third to the back</div>
</div>
<div>
<div class="card1 front">Fifth for the front</div>
</div>
<div>
<div class="padding back"></div>
<div class="card1 back">Fifth to the back</div>
</div>
</body>
</html>
<html>
<body>
<div>
<div class="card1 front">First for the front</div>
<div class="card2 front">Second for the front</div>
<div class="card3 front">Third for the front</div>
<div class="card4 front">Fourth for the front</div>
<div class="card5 front">Fifth for the front</div>
</div>
<div>
<div class="card3 back">Third to the back</div>
<div class="card2 back">Second to the back</div>
<div class="card1 back">First to the back</div>
<div class="padding back"></div>
<div class="card5 back">Fifth to the back</div>
<div class="card4 back">Fourth to the back</div>
</div>
</body>
</html>