Search code examples
javaxsltxalan

Restricting the letters used in a numbering generated by a xalan transformation


I am looking for a way to not have some letters in the numbering of chapters generated by xalan in an .xml to .fo transformation. I am using org.apache.xalan.xsltc.trax.TransformerFactoryImpl to transform an .xml file into an .fo file to later make a PDF out of it. In the xml file I have some numbered chapters like so :

<prcitem2 numbering="9">

They are transformed in the .fo like so : (This block is inside an fo:list-item-label, inside an fo:list-item, but I am on mobile and can't edit it properly. Sorry)

<fo:block>Й.</fo:block>

The xsl in charge of the transformation is :

<xsl:when test="ancestor-or-self::prcitem2">
<xsl:choose>
<xsl:when test="($language = 'ru')">
<xsl:number count="prcitem2" format="А."/>
</xsl:when>
</xsl:choose>

But my Russian comrades have informed me that some of their letters can't be used in numbering as it is not allowed by ATA and Russian standards (e.g. Й, З (that's not a 3) and some others). Is there a way to forbid the use of these letters ?


Solution

  • As I mentioned in comments, I don't see a way to "fix" the built-in xsl:number algorithm and I suggest you replace it with your own.

    In the following template, replace the alpha parameter's value with the Cyrillic characters you want to use. Everything else is self-adjusting.

    Note that the input numbering is expected to start at zero, so call the template with the decimal parameter's value being = "$your-number - 1".

    <xsl:template name="dec-to-alpha">
        <xsl:param name="decimal"/> 
        <xsl:param name="alpha" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
        <xsl:variable name="base" select="string-length($alpha)"/>
        <xsl:variable name="bit" select="$decimal mod $base"/>
        <xsl:variable name="char" select="substring($alpha, $bit + 1, 1)"/>
        <xsl:variable name="next" select="floor($decimal div $base)"/>
        <xsl:if test="$next">
            <xsl:call-template name="dec-to-alpha">
                <xsl:with-param name="decimal" select="$next - 1"/>
            </xsl:call-template>
        </xsl:if>
        <xsl:value-of select="$char"/>
    </xsl:template>
    

    Demo: https://xsltfiddle.liberty-development.net/94rmq74