Автоматическая нумерация заголовоков
От: rsn81 Россия http://rsn81.wordpress.com
Дата: 18.10.07 06:53
Оценка:
Добрый день.

Проблема

Очень неудобно, что в шаблоне нет автоматической нумерации заголовков, то есть абзацев стилей PART, SECTION, SUBSECTION — приходится нумеровать вручную, что при учете постоянных изменений статьи (перекомпоновки) заставляет уделять этому лишнее внимание и время.

Стандартная нумерация MS Word отражается некорректно в генерируемый XML, а стиль OL для нумерации заголовков не подходит — выше обсуждали про прерывание OL другими стилями. С другой стороны, а зачем нам вообще нумерация заголовков в XML? XML имеет иерархическую структуру, а потому шаблон XSL-преобразования может спокойно вычислить номер любого заголовка проанализировав XML-дерево на этапе построения HTML.

Решение (то, чем могу помочь я)

В принципе, автоматическую нумерацию заголовков и проставление номеров в содержании я сделал: изменил в articles.xsl соответствующие шаблоны PART, SECTION, SUBSECTION. Скорее всего сделал не очень красиво, можно было всю логику нумерации вынести всего в один шаблон (собственно — HEADER). Просто лень было сильно заморачиваться, сделал copy-paste-ом. В цитировании выделил внесенные изменения.

  1. Заголовки.

    <xsl:template match="PART">
        <xsl:if test="HEADER">
            <H2>
                <xsl:value-of select="count(preceding-sibling::PART/HEADER) + 1"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="HEADER"/>
                <A>
                    <xsl:attribute name="name"><xsl:value-of select="generate-id()"/></xsl:attribute>
                </A>
            </H2>
        </xsl:if>
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="PART/SECTION">
        <xsl:param name="pos"/>
        <H3>
            <xsl:value-of select="count(parent::PART/preceding-sibling::PART/HEADER) + 1"/>
            <xsl:text>.</xsl:text>
            <xsl:value-of select="count(preceding-sibling::SECTION) + 1"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="HEADER"/>
            <A>
                <xsl:attribute name="name"><xsl:value-of select="generate-id()"/></xsl:attribute>
            </A>
        </H3>
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="SUBSECTION">
        <H4>
            <xsl:value-of select="count(ancestor::PART/preceding-sibling::PART/HEADER) + 1"/>
            <xsl:text>.</xsl:text>
            <xsl:value-of select="count(parent::SECTION/preceding-sibling::SECTION) + 1"/>
            <xsl:text>.</xsl:text>
            <xsl:value-of select="count(preceding-sibling::SUBSECTION) + 1"/>
            <xsl:text> </xsl:text>
            <xsl:value-of select="HEADER"/>
        </H4>
        <xsl:apply-templates/>
    </xsl:template>

  2. Содержание.

    <xsl:if test="CONTENTS">
        <xsl:if test="not(COVER)">
            <DIV style="margin-left:2em">
                <xsl:for-each select="PART">
                    <A>
                        <xsl:attribute name="href">#<xsl:value-of select="generate-id()"/></xsl:attribute>
                        <xsl:if test="HEADER">
                            <B>
                                <xsl:value-of select="count(preceding-sibling::PART/HEADER) + 1"/>
                                <xsl:text> </xsl:text>
                                <xsl:value-of select="./HEADER"/>
                            </B>
                        </xsl:if>
                    </A>
                    <BR/>
                    <DIV style="margin-left:2em">
                        <xsl:for-each select="SECTION">
                            <A>
                                <xsl:attribute name="href">#<xsl:value-of select="generate-id()"/></xsl:attribute>
                                <xsl:value-of select="count(parent::PART/preceding-sibling::PART/HEADER) + 1"/>
                                <xsl:text>.</xsl:text>
                                <xsl:value-of select="count(preceding-sibling::SECTION) + 1"/>
                                <xsl:text> </xsl:text>
                                <xsl:value-of select="./HEADER"/>
                            </A>
                            <BR/>
                        </xsl:for-each>
                    </DIV>
                </xsl:for-each>
            </DIV>
        </xsl:if>
        <xsl:if test="COVER">
            <TABLE width="98%">
                <TR>
                    <TD valign="top" class="contents">
                        <xsl:for-each select="PART">
                            <xsl:if test="HEADER">
                                <A>
                                    <xsl:attribute name="href">#<xsl:value-of select="generate-id()"/></xsl:attribute>
                                    <B>
                                        <xsl:value-of select="count(preceding-sibling::PART/HEADER) + 1"/>
                                        <xsl:text> </xsl:text>
                                        <xsl:value-of select="./HEADER"/>
                                    </B>
                                </A>
                                <BR/>
                            </xsl:if>
                            <xsl:if test="SECTION">
                                <DIV style="margin-left:2em">
                                    <xsl:for-each select="SECTION">
                                        <xsl:if test="HEADER">
                                            <A>
                                                <xsl:attribute name="href">#<xsl:value-of select="generate-id()"/></xsl:attribute>
                                                <xsl:value-of select="count(parent::PART/preceding-sibling::PART/HEADER) + 1"/>
                                                <xsl:text>.</xsl:text>
                                                <xsl:value-of select="count(preceding-sibling::SECTION) + 1"/>
                                                <xsl:text> </xsl:text>
                                                <xsl:value-of select="./HEADER"/>
                                            </A>
                                            <BR/>
                                        </xsl:if>
                                    </xsl:for-each>
                                </DIV>
                            </xsl:if>
                        </xsl:for-each>
                    </TD>
                    <TD valign="top" align="center" class="contents">
                        <xsl:apply-templates select="COVER"/>
                    </TD>
                </TR>
            </TABLE>
        </xsl:if>
    </xsl:if>

Решение (то, что может сделать скорее всего только автор)

И все бы хорошо, но при внесении описанных выше изменений в шаблон articles.xsl заголовки всех старых статьей, в которых авторы мучались и расставляли нумерацию вручную, будут пронумерованы дважды, то есть увидим автоматический номер и далее текст ручной нумерации. Посему у меня просьба-предложение автору темы:
  1. Сделать настройку в свойствах документа "Автоматически нумеровать заголовки" — кнопка true/false. Она должна быть по умолчанию сброшена, но если выставлена, то в XML-документ должен быть сгенерирован, к примеру, такой элемент ARTICLE/AUTO-NUMBERING-HEADER.
  2. Внести в XSL-преобразование статьи указанные выше мною изменения, обернув их в <xsl:if test="ARTICLE/AUTO-NUMBERING-HEADER">...</xsl:if> — и в RSDN Authoring Pack, и на сайт.
  3. По возможности все же вынести всю логику формирования номера заголовка в шаблон HEADER.
И вуаля! И волки сыты, и овцы целы: старые статьи, пронумерованные вручную, и новые, пронумерованные автоматически, будут отображаться корректно.

Изменения по-моему плевые, не должны отнять и часа. Виталий, если у вас есть время, сделайте, пожалуйста, авторам RSDN хорошо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.