I'm trying to number the <para>s
, there is only one <para>
per crewDrillStep
but we can have nested crewDrillStep
s. It works as expected unless there is an <if>
block, then the numbering restarts. If I remove the <if>
then it numbers correctly.
I updated the example with Martin's suggestion which is so close, but there could be more than one crewDrill
and I noticed in some instances the numbering of the second level para
wasn't restarting. Also there are some paras with bullets in the xml which aren't to be numbered.
Given:
<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>
and:
<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>
Desired output:
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.
Actual output:
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.
CodePudding user response:
If I understand your intention right, then doing
<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>
instead of
<xsl:when test="count(ancestor::crewDrillStep)=2 ">
<xsl:attribute name="margin-left" select="'.25in'"/>
<xsl:number from="crewDrill" count="crewDrillStep" format="a. "/>
</xsl:when>
should give the wanted numbering for those second level para
s.
As an alternative to use the use of xsl:number
, one could define and use an accumulator:
<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"/>
and then output the number for each para
with e.g.
<xsl:template match="para">
<xsl:number
value="accumulator-before('para-count-seq')[last() - 1]"
format="{('1. ', 'a. ', '(1)')[count(current()/ancestor::crewDrillStep)]}"/>
</xsl:template>