xsl:number 问题以计算元素 XSLT 3.0 XSL-FO
Issue with xsl:number to count elements XSLT 3.0 XSL-FO
我正在尝试给 <para>s
编号,每个 crewDrillStep
只有一个 <para>
,但我们可以嵌套 crewDrillStep
。它按预期工作,除非有一个 <if>
块,然后重新开始编号。如果我删除 <if>
那么它的编号是正确的。
我根据 Martin 的建议更新了示例,该建议非常接近,但可能不止一个 crewDrill
我注意到在某些情况下第二层的编号 para
没有重新开始.此外,xml 中还有一些带项目符号的段落无需编号。
鉴于:
<crew>
<crewRefCard>
<title>Expanded Self-Test Procedures </title>
<crewDrill>
<if>
<caseCond>After program stops at test No. 1:</caseCond>
<crewDrillStep id="d1e21189">
<para>RESET switch - ELEC.</para>
</crewDrillStep>
<crewDrillStep id="d1e21195">
<para>Flip red switches:</para>
<crewDrillStep id="d1e21200">
<para>Right.</para>
</crewDrillStep>
<crewDrillStep id="d1e21206">
<para>Left.</para>
</crewDrillStep>
<crewDrillStep id="d1e21212">
<para>Rudder.</para>
</crewDrillStep>
</crewDrillStep>
<crewDrillStep id="d1e21219">
<para>Flip orange switch.</para>
<crewDrillStep id="d1e21224">
<para>Test No. advances to 2.</para>
</crewDrillStep>
<crewDrillStep id="d1e21230">
<para>Yellow caution light - On.</para>
</crewDrillStep>
<crewDrillStep id="d1e21236">
<para>Red warning light - On.</para>
</crewDrillStep>
<crewDrillStep id="d1e21242">
<para>Program stops.</para>
</crewDrillStep>
</crewDrillStep>
</crewDrill>
</crewRefCard>
</crew>
和:
<xsl:template name="para" match="para | notePara | warningAndCautionPara | attentionListItemPara">
<fo:block text-align="justify">
<xsl:choose>
<xsl:when test="self::para and (parent::crewDrillStep)">
<fo:block>
<xsl:choose>
<xsl:when test="count(ancestor::crewDrillStep)=1">
<xsl:number from="crewDrill" level="any" count="crewDrillStep"/>
</xsl:when>
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill/crewDrillStep" level="any" count="para[count(ancestor::crewDrillStep) = 2][not(starts-with(normalize-space(.),'•'))]" format="a. "/>
</xsl:when>
<xsl:when test="count(ancestor::crewDrillStep)=3">
<xsl:attribute name="margin-left" select="'.50in'"/>
<xsl:number from="crewDrill" count="crewDrillStep" format="(1) "/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</fo:block>
<fo:block>
<xsl:apply-templates select="node()" mode="include"/>
</fo:block>
</xsl:when>
</xsl:choose>
</fo:block>
</xsl:template>
期望的输出:
Expanded Self-Test Procedures
After program stops at test No. 1:
1. RESET switch - ELEC.
2. Flip red switches:
a. Right
b. Left.
c. Rudder.
3. Flip orange switch.
a. Test No. advances to 2.
b. Yellow caution light - On.
c. Red warning light - On.
d. Program stops.
实际输出:
Expanded Self-Test Procedures
After program stops at test No. 1:
1. RESET switch - ELEC.
2. Flip red switches:
a. Right
b. Left.
c. Rudder.
3. Flip orange switch.
d. Test No. advances to 2.
e. Yellow caution light - On.
f. Red warning light - On.
g. Program stops.
如果我理解你的意图是对的,那就做
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill/crewDrillStep" level="any" count="para[count(ancestor::crewDrillStep) = 2]" format="a. "/>
</xsl:when>
而不是
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill" count="crewDrillStep" format="a. "/>
</xsl:when>
应该为那些二级 para
提供所需的编号。
作为使用 xsl:number
的替代方法,可以定义和使用累加器:
<xsl:accumulator name="para-count-seq" as="xs:integer*" initial-value="()">
<xsl:accumulator-rule match="crewDrill" select="0"/>
<xsl:accumulator-rule match="crewDrill" phase="end" select="()"/>
<xsl:accumulator-rule match="crewDrillStep" select="$value, 0"/>
<xsl:accumulator-rule match="crewDrillStep" phase="end" select="$value[position() lt last()]"/>
<xsl:accumulator-rule match="para"
select="let $pos := count(ancestor::crewDrillStep)
return ($value[position() lt $pos], $value[$pos] + 1, $value[position() gt $pos])"/>
</xsl:accumulator>
<xsl:mode use-accumulators="para-count-seq"/>
然后输出每个 para
的数字,例如
<xsl:template match="para">
<xsl:number
value="accumulator-before('para-count-seq')[last() - 1]"
format="{('1. ', 'a. ', '(1)')[count(current()/ancestor::crewDrillStep)]}"/>
</xsl:template>
我正在尝试给 <para>s
编号,每个 crewDrillStep
只有一个 <para>
,但我们可以嵌套 crewDrillStep
。它按预期工作,除非有一个 <if>
块,然后重新开始编号。如果我删除 <if>
那么它的编号是正确的。
我根据 Martin 的建议更新了示例,该建议非常接近,但可能不止一个 crewDrill
我注意到在某些情况下第二层的编号 para
没有重新开始.此外,xml 中还有一些带项目符号的段落无需编号。
鉴于:
<crew>
<crewRefCard>
<title>Expanded Self-Test Procedures </title>
<crewDrill>
<if>
<caseCond>After program stops at test No. 1:</caseCond>
<crewDrillStep id="d1e21189">
<para>RESET switch - ELEC.</para>
</crewDrillStep>
<crewDrillStep id="d1e21195">
<para>Flip red switches:</para>
<crewDrillStep id="d1e21200">
<para>Right.</para>
</crewDrillStep>
<crewDrillStep id="d1e21206">
<para>Left.</para>
</crewDrillStep>
<crewDrillStep id="d1e21212">
<para>Rudder.</para>
</crewDrillStep>
</crewDrillStep>
<crewDrillStep id="d1e21219">
<para>Flip orange switch.</para>
<crewDrillStep id="d1e21224">
<para>Test No. advances to 2.</para>
</crewDrillStep>
<crewDrillStep id="d1e21230">
<para>Yellow caution light - On.</para>
</crewDrillStep>
<crewDrillStep id="d1e21236">
<para>Red warning light - On.</para>
</crewDrillStep>
<crewDrillStep id="d1e21242">
<para>Program stops.</para>
</crewDrillStep>
</crewDrillStep>
</crewDrill>
</crewRefCard>
</crew>
和:
<xsl:template name="para" match="para | notePara | warningAndCautionPara | attentionListItemPara">
<fo:block text-align="justify">
<xsl:choose>
<xsl:when test="self::para and (parent::crewDrillStep)">
<fo:block>
<xsl:choose>
<xsl:when test="count(ancestor::crewDrillStep)=1">
<xsl:number from="crewDrill" level="any" count="crewDrillStep"/>
</xsl:when>
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill/crewDrillStep" level="any" count="para[count(ancestor::crewDrillStep) = 2][not(starts-with(normalize-space(.),'•'))]" format="a. "/>
</xsl:when>
<xsl:when test="count(ancestor::crewDrillStep)=3">
<xsl:attribute name="margin-left" select="'.50in'"/>
<xsl:number from="crewDrill" count="crewDrillStep" format="(1) "/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</fo:block>
<fo:block>
<xsl:apply-templates select="node()" mode="include"/>
</fo:block>
</xsl:when>
</xsl:choose>
</fo:block>
</xsl:template>
期望的输出:
Expanded Self-Test Procedures
After program stops at test No. 1:
1. RESET switch - ELEC.
2. Flip red switches:
a. Right
b. Left.
c. Rudder.
3. Flip orange switch.
a. Test No. advances to 2.
b. Yellow caution light - On.
c. Red warning light - On.
d. Program stops.
实际输出:
Expanded Self-Test Procedures
After program stops at test No. 1:
1. RESET switch - ELEC.
2. Flip red switches:
a. Right
b. Left.
c. Rudder.
3. Flip orange switch.
d. Test No. advances to 2.
e. Yellow caution light - On.
f. Red warning light - On.
g. Program stops.
如果我理解你的意图是对的,那就做
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill/crewDrillStep" level="any" count="para[count(ancestor::crewDrillStep) = 2]" format="a. "/>
</xsl:when>
而不是
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill" count="crewDrillStep" format="a. "/>
</xsl:when>
应该为那些二级 para
提供所需的编号。
作为使用 xsl:number
的替代方法,可以定义和使用累加器:
<xsl:accumulator name="para-count-seq" as="xs:integer*" initial-value="()">
<xsl:accumulator-rule match="crewDrill" select="0"/>
<xsl:accumulator-rule match="crewDrill" phase="end" select="()"/>
<xsl:accumulator-rule match="crewDrillStep" select="$value, 0"/>
<xsl:accumulator-rule match="crewDrillStep" phase="end" select="$value[position() lt last()]"/>
<xsl:accumulator-rule match="para"
select="let $pos := count(ancestor::crewDrillStep)
return ($value[position() lt $pos], $value[$pos] + 1, $value[position() gt $pos])"/>
</xsl:accumulator>
<xsl:mode use-accumulators="para-count-seq"/>
然后输出每个 para
的数字,例如
<xsl:template match="para">
<xsl:number
value="accumulator-before('para-count-seq')[last() - 1]"
format="{('1. ', 'a. ', '(1)')[count(current()/ancestor::crewDrillStep)]}"/>
</xsl:template>