我总共有 10 个
Detail
元素,如下所示,因为我想根据指标 Code
值拆分和排列 Plan
元素值。
<Details>
<Detail>
<Code>001</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>002</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>003</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>004</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>005</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>006</Code>
<Type>Alt</Type>
<Plan>Y</Plan>
</Detail>
<Detail>
<Code>007</Code>
<Type>Alt</Type>
<Plan>Y</Plan>
</Detail>
<Detail>
<Code>008</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>009</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
<Detail>
<Code>010</Code>
<Type>Alt</Type>
<Plan>N</Plan>
</Detail>
</Details>
每页我只需要 5 个代码或行来允许,因为我希望
Plan='N'
代码应该放在第一位,Plan='Y'
代码应该放在下面,我已经尝试了下面的代码
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0" exclude-result-prefixes="xs">
<xsl:template match="Details">
<xsl:call-template name="Table_Left">
<xsl:with-param name="start_row" as="xs:integer">1</xsl:with-param>
<xsl:with-param name="end_row" as="xs:integer">10</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="Table_Left">
<xsl:param name="start_row" as="xs:integer">0</xsl:param>
<xsl:param name="end_row" as="xs:integer">0</xsl:param>
<xsl:variable name="Details" select="Details"/>
<xsl:variable name="total_rows">
<xsl:value-of select="count($Details//Detail[Type = 'Alt'])"/>
</xsl:variable>
<xsl:variable name="sorted_plans_alt" as="element()">
<sorted_plans>
<xsl:for-each select="$Details//Detail[Type = 'Alt']">
<xsl:sort select=".//Detail[Type = 'Alt']"
order="ascending" data-type="number"/>
<xsl:sequence select="."/>
</xsl:for-each>
</sorted_plans>
</xsl:variable>
<xsl:variable name="plans_subset">
<xsl:sequence
select="
subsequence($sorted_plans_alt//Detail[Type = 'Alt'], $start_row, $end_row)"
/>
</xsl:variable>
<xsl:variable name="preceding_plan" as="element()">
<preceding_plan>
<xsl:choose>
<xsl:when test="$start_row = 1">
<empty/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence
select="subsequence($sorted_plans_alt//Detail[Type = 'Alt'], $start_row - 1, 1)"
/>
</xsl:otherwise>
</xsl:choose>
</preceding_plan>
</xsl:variable>
<xsl:variable name="rows_to_output" as="xs:integer">
<xsl:variable name="number_of_r_plans" as="xs:integer">
<xsl:value-of
select="count($Details//Detail[Type = 'Alt'])"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$number_of_r_plans > 0">
<xsl:value-of select="$end_row - 5"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$end_row"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="left_table" as="element()">
<xsl:for-each select="($plans_subset//Detail[Type = 'Alt'][Plan='N'])[position() <= $rows_to_output]">
<xsl:value-of select="current()/Code"/>
</xsl:for-each>
<xsl:for-each select="($plans_subset//Detail[Type = 'Alt'][Plan='Y'])[position() <= $rows_to_output]">
<xsl:value-of select="current()/Code"/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="right_table">
<topic id="topic_1" xml:lang="en-US">
<xsl:apply-templates select="$left_table/*"/>
</topic>
</xsl:variable>
<xsl:sequence select="$right_table"/>
<xsl:choose>
<xsl:when test="$start_row + $rows_to_output <= $total_rows">
<xsl:call-template name="Table_Left">
<xsl:with-param name="start_row" as="xs:integer"
select="$start_row + $rows_to_output"/>
<xsl:with-param name="end_row" as="xs:integer" select="$end_row"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$start_row = 999"/>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
在下面的输出中,我在第一页中得到 7 个代码(即使在 xsl 中提到,每页也只有 5 个代码)。但我也收到了
Plan='Y'
(006 和 007)代码。
1st page 2nd page
001 008
002 009
003 010
004
005
006
007
预期输出如下,第一页有 5 个代码,第二页有剩余代码。我需要
Plan=N
代码应该放在第一位,Plan=Y
代码应该放在后面
1st page 2nd page
001 008
002 009
003 010
004 006
005 007
预期输出的格式不清楚。
尝试以下方法:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Details">
<!-- sort plan N first -->
<xsl:variable name="sorted">
<xsl:perform-sort>
<xsl:sort select="Plan='Y'"/>
<xsl:sequence select="Detail"/>
</xsl:perform-sort>
</xsl:variable>
<!-- output in groups of 5 per page -->
<output>
<xsl:for-each-group select="$sorted/Detail" group-adjacent="(position() - 1) idiv 5">
<page>
<xsl:copy-of select="current-group()/Code"/>
</page>
</xsl:for-each-group>
</output>
</xsl:template>
</xsl:stylesheet>
使用提供的输入,输出将是:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<page>
<Code>001</Code>
<Code>002</Code>
<Code>003</Code>
<Code>004</Code>
<Code>005</Code>
</page>
<page>
<Code>008</Code>
<Code>009</Code>
<Code>010</Code>
<Code>006</Code>
<Code>007</Code>
</page>
</output>
我不清楚你到底想要什么输出,但这里有一些关于你的代码的观察结果,其中一些纯粹是风格上的。
<xsl:with-param name="start_row" as="xs:integer">1</xsl:with-param>
使用
<xsl:with-param name="start_row" as="xs:integer" select="1"/>
它避免了类型转换(从文本节点到整数)。有些人主张始终使用
as
子句,但我会将其留在这里,因为很明显 select="1"
会给您一个 xs:integer
。
<xsl:variable name="total_rows">
<xsl:value-of select="count($Details//Detail[Type = 'Alt'])"/>
</xsl:variable>
使用
<xsl:variable name="total_rows" select="count($Details/Detail[Type = 'Alt'])"/>
您确实不想在这里构建 XML 文档,您想计算一个整数。
当您知道
//
元素将是 Detail
的直接子元素时,搜索所有后代 (Details
) 是没有意义的。
<xsl:for-each select="$Details//Detail[Type = 'Alt']">
<xsl:sort select=".//Detail[Type = 'Alt']"
这是错误的。排序键是相对于您要排序的元素计算的,您的选择表达式不会选择任何内容。我不知道如何纠正它,因为我不知道你真正想要排序的内容。
<xsl:variable name="left_table" as="element()">
<xsl:for-each select="($plans_subset//Detail[Type = 'Alt'][Plan='N'])[position() <= $rows_to_output]">
<xsl:value-of select="current()/Code"/>
</xsl:for-each>
<xsl:for-each select="($plans_subset//Detail[Type = 'Alt'][Plan='Y'])[position() <= $rows_to_output]">
<xsl:value-of select="current()/Code"/>
</xsl:for-each>
</xsl:variable>
这是错误的,因为您的变量将由文本节点组成(由
xsl:value-of
生成,而不是元素)。也许您有意xsl:copy-of
。
current()/Code
是 Code
的一种冗长说法。
恐怕这些都是细节问题,我怀疑我只见树木不见森林。我怀疑有一些更根本的问题;我不明白你想要实现什么,但我在需求中没有看到任何表明递归命名模板是实现它的适当方法。