Преобразование типографских сносок в стиль документальной книги - PullRequest
0 голосов
/ 16 июня 2020

У меня есть куча содержимого, содержащего таблицы calstables, где сноски были сделаны с использованием методов набора, с каждым из индексов, установленных с использованием элементов <sup/>, и каждая из сносок включена в свою собственную строчку в конце таблицы.

Я хочу преобразовать их, чтобы использовать разметку сносок Docbook, например this и this

Пример данных выглядит следующим образом (я добавил <from/> и <to/>, чтобы показать, откуда он исходит и где ему нужно go to)

<testdata>
   <from>
      <table>
         <tgroup cols="3">
            <colspec colname="1" colnum="1" colwidth="39pt" align="left"/>
            <colspec colname="2" colnum="2" colwidth="39pt" align="center"/>
            <colspec colname="3" colnum="3" colwidth="39pt" align="center"/>
            <thead>
               <row valign="bottom">
                  <entry>Item</entry>
                  <entry>ItemA</entry>
                  <entry>ItemB<sup>1</sup></entry>
               </row>
            </thead>
            <tbody>
               <row valign="top">
                  <entry>Entry 1</entry>
                  <entry>60</entry>
                  <entry>3.2</entry>
               </row>
               <row>
                  <entry>Entry A</entry>
                  <entry>150</entry>
                  <entry>3.55<sup>2</sup></entry>
               </row>
               <row>
                  <entry>This entry</entry>
                  <entry>260<sup>3</sup></entry>
                  <entry>3.55<sup>2</sup></entry>
               </row>
               <row>
                  <entry align="left" namest="1" nameend="3"><sup>1</sup> LAT</entry>
               </row>
               <row>
                  <entry align="left" namest="1" nameend="3"><sup>2</sup> Itemvalue &lt;24.5 m. Also see note below.</entry>
               </row>
               <row>
                  <entry align="left" namest="1" nameend="3"><sup>3</sup> Ramp up 19.8 m.</entry>
               </row>
            </tbody>
         </tgroup>
      </table>   
   </from>
   <to>
      <table>
         <tgroup cols="3">
            <colspec colname="1" colnum="1" colwidth="39pt" align="left"/>
            <colspec colname="2" colnum="2" colwidth="39pt" align="center"/>
            <colspec colname="3" colnum="3" colwidth="39pt" align="center"/>
            <thead>
               <row valign="bottom">
                  <entry>Item</entry>
                  <entry>ItemA</entry>
                  <entry>ItemB<footnote id="1">LAT</footnote></entry>
               </row>
            </thead>
            <tbody>
               <row valign="top">
                  <entry>Entry 1</entry>
                  <entry>60</entry>
                  <entry>3.2</entry>
               </row>
               <row>
                  <entry>Entry A</entry>
                  <entry>150</entry>
                  <entry>3.55<footnote id="2">Itemvalue &lt;24.5 m. Also see note below.</footnote></entry>
               </row>
               <row>
                  <entry>This entry</entry>
                  <entry>260<footnote id="3">Ramp up 19.8 m.</footnote></entry>
                  <entry>3.55<footnoteref linkend="2"/></entry>
               </row>
            </tbody>
         </tgroup>
      </table>   
   </to>
</testdata>

Лог c довольно просто сформулировать:

1. Copy everthing to output, unless ...
2. it contains a `<sup/>` element, in which case either
    1. if it has a `@nameend` attribute, do nothing, or 
    2. if it is the first instance of this index, create a footnote element with an `@id` attribute, grabbing the content from the matching straddle row, or
    3. if it's not the first instance, create a footnoteref element, with a matching `@linkend` attribute

Конечно, есть и множество проверок ошибок, но сейчас меня это не особо беспокоит.

Я могу обратиться к каждому из пунктов 2 выше, используя набор индивидуальных шаблонов совпадений, например

<xsl:template match="sup[text() = '1'][1]">
<xsl:template match="sup[text() = '2'][1]">
<xsl:template match="sup[text() = '3'][1]">

но я полагаю, что должен быть более элегантный шаблон соответствия (возможно, с использованием ключей?), Чтобы соответствовать первому экземпляру каждого используемого индекса, но, хоть убей, я не могу представить, что это может быть.

* 1 024 * До сих пор я определил 2 ключа
<xsl:key name="fn-indices" match="sup" use="number(.)"/>
<xsl:key name="fn-text" match="entry[sup][@nameend &gt; @namest]" use="number(sup)"/>

Но я не уверен, как лучше их использовать?

Любые предложения по элегантному шаблону соответствия для 1-го экземпляра каждого индекса ?

Ответы [ 2 ]

1 голос
/ 16 июня 2020

sup[. is key('fn-indices', number())[1]] должно соответствовать первому элементу в каждой «группе», чтобы вы могли заменить

<xsl:template match="sup[text() = '1'][1]">
<xsl:template match="sup[text() = '2'][1]">
<xsl:template match="sup[text() = '3'][1]">

на

<xsl:template match="sup[. is key('fn-indices', number())[1]]">

Оператор is проверяет идентичность узла .

0 голосов
/ 17 июня 2020

Итак, я придумал этот шаблон, который, кажется, делает то, что я хочу

Примечание: Я сократил footnote до fn и footnoteref до fnref во избежание конфликтов с другими процессами на данный момент.

Также вместо is я использовал generate-id(), который соответствует 1.0, но я, вероятно, изменю это со временем

<xsl:template match="sup" mode="sup2fn" priority="10">
    <xsl:variable name="index" select="number(normalize-space(.))"/>
    <xsl:variable name="this-table" select="ancestor::*[local-name() = 'table']"/>
    <xsl:variable name="fn-text-nodes" select="key('fn-text',$index)[generate-id(ancestor::*[local-name() = 'table']) = generate-id($this-table)][1]"/>
    <xsl:variable name="idref-here" select="generate-id(.)"/>
    <xsl:variable name="instance-1" select="key('fn-indices',$index)[generate-id(ancestor::*[local-name() = 'table']) = generate-id($this-table)][1]"/>
    <xsl:variable name="idref-target" select="generate-id($instance-1)"/>
    <xsl:variable name="fn-text">
        <xsl:apply-templates select="$fn-text-nodes/node()" mode="make-footnote-text"/>
    </xsl:variable>
    <xsl:choose>
        <xsl:when test="generate-id(.) = generate-id($instance-1) ">
            <fn id="{$idref-here}">
                <xsl:if test="$debug = 'yes'">
                    <xsl:attribute name="index"><xsl:value-of select="$index"/></xsl:attribute>
                </xsl:if><xsl:value-of select="normalize-space($fn-text)"/></fn>
        </xsl:when>
        <xsl:otherwise>
            <fnref linkend="{$idref-target}">
                <xsl:if test="$debug = 'yes'">
                    <xsl:attribute name="index"><xsl:value-of select="$index"/></xsl:attribute>
                </xsl:if>
            </fnref>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Мне также приходилось учитывать возможность наличия нескольких таблиц, поэтому я проверяю, что узлы sup имеют одного и того же родителя. Интересно, может ли это быть более эффективным в определении ключа?

Также я сохранил исходный индекс для целей отладки, а также для создания новых id атрибутов. Наконец, вместо использования отдельных шаблонов сопоставления у меня есть один шаблон sup и использовали там ветку <xsl:choose>, чтобы проверить, является ли это первым или последующим экземпляром <sup>

...