0

Been struggling with this for a bit and now going to ask for help. I am trying to get the correct number for a step to appear when referencing it on PDF output when using XSL-FO. With help previously gotten here I have other references working as desired. These particular tags are giving me trouble.

This is for a fault isolation tree in the S1000D aerospace publication spec:

<isolationStep id="step4"><isolationStepQuestion>Check for burnt-out lamps. Are lamps good?</isolationStepQuestion><isolationStepAnswer><yesNoAnswer><yesAnswer nextActionRefId="step6"/><noAnswer nextActionRefId="step8"/></yesNoAnswer></isolationStepAnswer></isolationStep>

As you can see there is an answer section for the question. Those answers have refIds to other steps. In the PDF I am getting the steps to be numbered correctly, but when rendering the answers I am getting this:

enter image description here

The XSL-FO used for the questions, answers, and the attempt to number to answer referenced steps:

<xsl:template match="isolationStep | isolationProcedureEnd">
    <xsl:for-each select="note">
        <fo:block font-weight="bold">Note</fo:block>
        <xsl:apply-templates/>
    </xsl:for-each>
    <xsl:for-each select="caution">
        <fo:block font-weight="bold" text-align="center">CAUTION</fo:block>
        <xsl:apply-templates/>
    </xsl:for-each>
    <xsl:for-each select="warning">
        <fo:block font-weight="bold" text-align="center">WARNING</fo:block>
        <xsl:apply-templates/>
    </xsl:for-each>
    <fo:block id="{@id}" padding="5pt" font-size="10pt">
        <!-- border-style="solid"
              border-width=".1mm"-->
        <!--<xsl:apply-templates/>-->
        <fo:list-block space-after="2mm">
            <fo:list-item>
                <fo:list-item-label end-indent="label-end()">
                    <fo:block>
                        <xsl:number level="multiple" count="isolationMainProcedure/isolationStep | isolationProcedureEnd" format="1."/>
                    </fo:block>
                </fo:list-item-label>
                <fo:list-item-body start-indent="body-start()">
                    <fo:block>
                        <!--<xsl:apply-templates select="title"/>-->
                        <xsl:choose>
                            <xsl:when test="count(action) &gt; 1">
                                <xsl:for-each select="action">
                                    <fo:list-block space-after="2mm">
                                        <fo:list-item>
                                            <fo:list-item-label end-indent="label-end()">
                                            <fo:block>
                                            <xsl:number format="a."/>
                                            </fo:block>
                                            </fo:list-item-label>
                                            <fo:list-item-body start-indent="body-start()">
                                            <fo:block>
                                            <xsl:apply-templates/>
                                            </fo:block>
                                            </fo:list-item-body>
                                        </fo:list-item>
                                    </fo:list-block>
                                    <!--<xsl:apply-templates/>-->
                                </xsl:for-each>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:for-each select="action">
                                    <fo:block>
                                        <xsl:apply-templates/>
                                    </fo:block>
                                    <!--<xsl:apply-templates/>-->
                                </xsl:for-each>
                            </xsl:otherwise>
                        </xsl:choose>
                        
                        <xsl:apply-templates select="isolationStepQuestion"/>
                        <xsl:apply-templates select="isolationStepAnswer"/>
                    </fo:block>
                </fo:list-item-body>
            </fo:list-item>
        </fo:list-block>
    </fo:block>
</xsl:template>


<xsl:template match="isolationStep | isolationProcedureEnd" mode="nbr">
    <xsl:variable name="origNbr">
        <xsl:number level="multiple" format="1"/>            
    </xsl:variable>
    <xsl:value-of select="$origNbr"/>
</xsl:template>

<xsl:template match="isolationStepQuestion">
    <fo:block font-weight="bold">
        <xsl:value-of select="."/>
    </fo:block>
</xsl:template>

<xsl:template match="yesNoAnswer">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="yesAnswer">
    <xsl:variable name="ref" select="@nextActionRefId"/>
    <fo:block space-before="4pt" space-after="4pt" keep-with-previous="always">
        <fo:inline><xsl:text>Yes: Go to </xsl:text>
            <fo:basic-link internal-destination="{@nextActionRefId}" color="blue">Step  <!--<xsl:value-of select="$yesref2"/>-->
                <!--ancestor::isolationMainProcedure-->
                <!--<xsl:apply-templates select="an../../../.././isolationStep | isolationProcedureEnd[@id=$yesref]" mode="nbr"/> ancestor::isolationMainProcedure[1]/-->
                <xsl:apply-templates select="//isolationStep | isolationProcedureEnd[@id=$ref]" mode="nbr"/>
            </fo:basic-link></fo:inline>
    </fo:block>
</xsl:template>

<xsl:template match="noAnswer">
    <xsl:variable name="ref" select="@nextActionRefId"/>
    <fo:block keep-with-previous="always">
        <fo:inline>
            <xsl:text>No: Go to </xsl:text>
            <fo:basic-link internal-destination="{@nextActionRefId}" color="blue">Step 
                <xsl:apply-templates select="//isolationStep | isolationProcedureEnd[@id=$ref]" mode="nbr"/>
            </fo:basic-link></fo:inline>
    </fo:block>
</xsl:template>

<xsl:template match="isolationStepAnswer">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="isolationStep | isolationProcedureEnd" mode="nbr">
    <xsl:variable name="origNbr">
        <xsl:number level="multiple" format="1"/>            
    </xsl:variable>
    <xsl:value-of select="$origNbr"/>
</xsl:template>

Also, the links are working, and takes you to the correct location. I just am having issues getting it to number correctly.

This is an XSL 2.0 stylesheet. Any help is appreciated, thanks in advance.

Community
  • 1
  • 1
twfurst
  • 165
  • 2
  • 13

1 Answers1

2

The //isolationStep is selecting every isolationStep in the document, so you're getting the number of each of them.

You might have been trying to have the effect of "//isolationStep[@id=$ref] | //isolationProcedureEnd[@id=$ref], but you'd probably be better of using a key for looking up isolationStep and isolationProcedureEnd by their IDs.


Keys are defined at http://www.w3.org/TR/xslt20/#key

You could define a key for lookup of isolationStep elements by their @id as a top-level element in the stylesheet:

<xsl:key name="isolationSteps"
         match="isolationStep"
         use="@id" />

and in your template, use the key() function to find the isolationStep with the matching @id value:

<xsl:template match="yesAnswer">
    <xsl:variable name="ref" select="@nextActionRefId"/>
    <fo:block space-before="4pt" space-after="4pt" keep-with-previous="always">
        <fo:inline><xsl:text>Yes: Go to </xsl:text>
            <fo:basic-link internal-destination="{@nextActionRefId}" color="blue">Step  <!--<xsl:value-of select="$yesref2"/>-->
                <!--ancestor::isolationMainProcedure-->
                <!--<xsl:apply-templates select="an../../../.././isolationStep | isolationProcedureEnd[@id=$yesref]" mode="nbr"/> ancestor::isolationMainProcedure[1]/-->
                <xsl:apply-templates select="key('isolationSteps', $ref)" mode="nbr"/>
            </fo:basic-link></fo:inline>
    </fo:block>
</xsl:template>
Tony Graham
  • 7,306
  • 13
  • 20
  • I am not familiar with using keys for this, could show me how this could be implemented? – twfurst Sep 28 '15 at 16:54
  • I added an (untested) example. – Tony Graham Sep 29 '15 at 09:01
  • Didn't think it was really that simple. One question, the isolationStep and isolationProcedureEnd elements need to be counted at the same time, as they are siblings. Can the key match either or? I will test here momentarily. Thanks. – twfurst Sep 29 '15 at 12:01
  • I'd say that all you need is `` (or maybe `` if there's other sibling elements). In fact, that should be all that you need as the content of your `xsl:template`: you don't need the `xsl:variable` and `xsl:value-of` since `xsl:number` returns a text node anyway. See http://www.w3.org/TR/xslt20/#numbering-based-on-position – Tony Graham Sep 29 '15 at 12:36
  • Do `yesAnswer` and `noAnswer` also refer to `isolationProcedureEnd` elements? If so, you'd need to change the `xsl:key/@match` to `match="isolationStep | isolationProcedureEnd"` so you can also lookup `isolationProcedureEnd` elements. – Tony Graham Sep 29 '15 at 12:39
  • Yes, the `yesAnswer` and `noAnswer` can refer to either element. I did make my key look for both, but it numbered them independent of one another. I am adjusting the count to "*" as you suggested and will see if i get a better result. – twfurst Sep 29 '15 at 16:20
  • The key is just for finding the right element. It's independent of using `xsl:number` to generate the number. The bit in http://www.w3.org/TR/xslt20/#numbering-based-on-position about "If count attribute is not specified, then it defaults to the pattern that matches any node with the same node kind as the selected node and, if the selected node has an expanded-QName, with the same expanded-QName as the selected node." boils down to counting the same-named elements when `@count` is absent. – Tony Graham Sep 29 '15 at 17:02
  • Have it figured out now. The key: `` and the template: ` ` Thanks for the help. – twfurst Sep 29 '15 at 17:45
  • You can reduce your template to ` ` since you're currently duplicating default values of the attributes and generating a text node from a variable that contains a text node. – Tony Graham Sep 29 '15 at 18:15