Как преобразовать XML в PDF с помощью XSLT, используя символы экспоненты в XML

#xml #pdf #xsl-fo #apache-fop #exponent

#xml #PDF #xsl-fo #apache-fop #экспонента

Вопрос:

Я пытаюсь распечатать свои формулы с экспонентами в формате PDF, используя xml, xsl и fo для преобразования из xml в pdf и в html. В html у меня нет проблем, все показатели отображаются правильно. возможно, потому, что браузеры будут отображать все символы utf-8. но, похоже, apache fop этого не сделает.

Есть ли кто-нибудь, кто может мне помочь, дать мне совет или показать мне, как это сделать. я не думаю, что я первый человек, которому нужно печатать экспоненты в формате PDF с помощью преобразований fo. единственный способ, которым мне удалось распечатать экспоненту, — это вручную написать встроенные теги и изменить смещение базовой линии на «перемещение» символов выше, но я думаю, что это не очень хорошее решение.

Следующие файлы примеров покажут мою проблему. В xsl-файле я попробовал некоторые вещи

xml-файл:

 <?xml version="1.0" encoding="utf-8"?>
<demo>
    <formulas>
      <formula>0,2 µm   3 · 10⁻⁶ · a</formula>
      <formula>0,3 µm   4 · 10⁻³ · b</formula>
      <formula>0,4 µm   5 · E-6 · c</formula>
      <formula>0,5 µm   6 · E-3 · d</formula>
    </formulas>
</demo>
  

xsl-файл с некоторыми попытками:

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fo="http://www.w3.org/1999/XSL/Format"
    xmlns:own="http://www.own.com"
    >

    <xsl:template match="/demo">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="master_demo" page-width="21.0cm" page-height="29.7cm" margin-top="0.5cm" margin-bottom="0.25cm" margin-left="2.0cm" margin-right="1.0cm">
                    <fo:region-body region-name="flow_demo" margin-top="0.0cm" margin-bottom="0.85cm" />
                    <fo:region-before extent="4.5cm" />
                    <fo:region-after extent="0.5cm"/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <fo:page-sequence master-reference="master_demo">
                <fo:flow flow-name="flow_demo">
                    <fo:block-container absolute-position="fixed" top="5.0cm" margin-left="1.0cm">
                        <fo:block>
                            <fo:table>
                                <fo:table-column column-width="6.0cm"/>
                                <fo:table-column column-width="6.0cm"/>
                                <fo:table-column column-width="6.0cm"/>
                                <fo:table-body>
                                    <xsl:for-each select="formulas/formula">
                                        <fo:table-row>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    Test:amp;#160;<xsl:value-of select="own:GetFormattedFormulaPDF(.)"/>
                                                </fo:block>
                                            </fo:table-cell>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    Test:amp;#160;<xsl:copy-of select="own:GetFormattedFormulaPDF(.)"></xsl:copy-of>
                                                </fo:block>
                                            </fo:table-cell>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    Test:amp;#160;amp;#8254;amp;#179;amp;#8254;amp;#179;amp;#8315;
                                                </fo:block>
                                            </fo:table-cell>
                                        </fo:table-row>
                                    </xsl:for-each>
                                </fo:table-body>
                            </fo:table>

                            <fo:table margin-top="2.0cm">
                                <fo:table-column column-width="10.0cm"/>
                                <fo:table-body>
                                    <xsl:for-each select="formulas/formula">
                                        <fo:table-row>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    XML-Text:amp;#160;<xsl:value-of select="."/>
                                                </fo:block>
                                            </fo:table-cell>
                                        </fo:table-row>
                                    </xsl:for-each>
                                </fo:table-body>
                            </fo:table>

                            <fo:table margin-top="2.0cm">
                                <fo:table-column column-width="10.0cm"/>
                                <fo:table-body>
                                    <xsl:for-each select="formulas/formula">
                                        <fo:table-row>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    <xsl:call-template name="mu">
                                                        <xsl:with-param name="formula" select = "." />
                                                    </xsl:call-template>
                                                </fo:block>
                                            </fo:table-cell>
                                        </fo:table-row>
                                    </xsl:for-each>
                                </fo:table-body>
                            </fo:table>

                            <fo:table margin-top="2.0cm">
                                <fo:table-column column-width="10.0cm"/>
                                <fo:table-body>
                                    <xsl:for-each select="formulas/formula">
                                        <fo:table-row>
                                            <fo:table-cell>
                                                <fo:block font-size="9pt" font-family="SansSerif" margin-top="0.2cm">
                                                    Formula with fo-tags:amp;#160;0,9 µm   5 · 10<fo:inline font-size="7pt" baseline-shift="40%">–4</fo:inline> · <fo:inline font-style="italic">abc</fo:inline>
                                                </fo:block>
                                            </fo:table-cell>
                                        </fo:table-row>
                                    </xsl:for-each>
                                </fo:table-body>
                            </fo:table>

                        </fo:block>
                    </fo:block-container>
                </fo:flow>
            </fo:page-sequence>

        </fo:root>
    </xsl:template>
    
    <xsl:function name="own:GetFormattedFormulaPDF" as="xs:string">
        <xsl:param name="mu" as="xs:string"></xsl:param>
        <xsl:choose>
            <xsl:when test="contains($mu, '10⁻³')">
                <xsl:variable name="E-3d">
                    10<fo:inline font-size="7pt" baseline-shift="40%">–3</fo:inline> · <fo:inline font-style="italic">d</fo:inline>
                </xsl:variable>
                <xsl:value-of select="concat(substring-before($mu, '10⁻³'),$E-3d)"/>
            </xsl:when>
            <xsl:when test="contains($mu, '10⁻⁶')">
                <xsl:variable name="E-6d">
                    10<fo:inline font-size="7pt" baseline-shift="40%">–6</fo:inline> · <fo:inline font-style="italic">d</fo:inline>
                </xsl:variable>
                <xsl:value-of select="concat(substring-before($mu, '10⁻⁶'),$E-6d)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="formel">
                    Formel direkt -> 50<fo:inline font-size="7pt" baseline-shift="40%">–12</fo:inline> · <fo:inline font-style="italic">dx</fo:inline>
                </xsl:variable>
                <xsl:value-of select="$formel"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>
    
    <xsl:template name="mu">
        <xsl:param name="formula"></xsl:param>
        <xsl:choose>
            <xsl:when test="contains($formula, '10⁻³')">
                <xsl:variable name="E-3d">
                    Hier Minus 3 -> 10<fo:inline font-size="7pt" baseline-shift="40%">–3</fo:inline> · <fo:inline font-style="italic">d</fo:inline>
                </xsl:variable>
                <xsl:value-of select="concat(substring-before($formula, '10⁻³'),$E-3d)"/>
            </xsl:when>
            <xsl:when test="contains($formula, '10⁻⁶')">
                <xsl:variable name="E-6d">
                    Hier Minus 6 -> 10<fo:inline font-size="7pt" baseline-shift="40%">–6</fo:inline> · <fo:inline font-style="italic">d</fo:inline>
                </xsl:variable>
                <xsl:value-of select="concat(substring-before($formula, '10⁻⁶'),$E-6d)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:variable name="formel">
                    Formel direkt -> 50<fo:inline font-size="7pt" baseline-shift="40%">–12</fo:inline> · <fo:inline font-style="italic">dx</fo:inline>
                </xsl:variable>
                <xsl:value-of select="$formel"/>
            </xsl:otherwise>
        </xsl:choose>        
    </xsl:template>

</xsl:stylesheet>
  

Ответ №1:

Встроенные элементы, вероятно, являются более распространенным способом. Это, безусловно, был мой опыт.

Таким образом, мое единственное предложение для ваших встроенных тегов — использовать baseline-shift="super" (см. https://www.w3.org/TR/xsl11/#baseline-shift ), который должен использовать базовый верхний индекс, встроенный в шрифт.

Что касается того, почему встроенные элементы, есть несколько причин:

  • Если вы хотите представлять более сложные формулы, вам лучше использовать MathML, а не обычный текст. (AFAICT, FOP нуждается в JEuclid, чтобы иметь возможность отображать MathML, но AH Formatter поддерживает MathML 3 изначально.)
  • Стандарт Unicode не поощряет использование символов нижнего и верхнего индексов. Из «Стандарта Unicode, версии 6.2» (старый, но под рукой), раздел 15.4, символы верхнего и нижнего индексов:

В общем, стандарт Unicode не пытается описать расположение символа выше или ниже базовой линии в типографском макете. Поэтому предпочтительным способом кодирования надстрочных букв или цифр, таких как «1 st» или «DC00 16«, является стиль или разметка в форматированном тексте.

  • Вы не можете быть уверены, что каждый шрифт содержит цифры с надстрочным индексом, поэтому также безопаснее использовать разметку и стили, чем ожидать, что каждая цифра с надстрочным индексом будет отображаться правильно.