Странное поведение с шаблоном xsl: text и double и text () / identity - PullRequest
0 голосов
/ 03 июня 2018

Я хочу преобразовать следующий xml вход:

<?xml version="1.0" encoding="utf-8"?>
<doc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <title>title</title>
    <foo>x</foo>
</doc>

В этот вывод

\section{title}

x

Я пробовал xsl лист:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" indent="no"/>

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

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="title">
        <xsl:text>\section{</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>}&#xd;&#xa;</xsl:text>
    </xsl:template>

    <xsl:template match="foo">
        <xsl:value-of select="."/>
    </xsl:template>
</xsl:stylesheet>

Но выходные данные имели завершающие пробелы и были с отступом, вот так:

    \section{title}

    x

Теперь после некоторого поиска я обнаружил, что, если я отключил template на text(), я мог бы получить что-то, что хотел,Я заменил шаблон идентификации следующим:

<xsl:template match="@*|node()">
    <xsl:choose>
        <xsl:when test="self::text()"/>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

При применении к входу xml он дал мне следующее:

\section{title}
x

Так что, очевидно, новая строка &#xa; исчезла,Что я понимаю еще меньше, если я изменю таблицу стилей, добавив еще &#xa; к этому:

<xsl:template match="title">
    <xsl:text>\section{</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>}&#xd;&#xa;</xsl:text>
</xsl:template>

к

 <xsl:template match="title">
    <xsl:text>\section{</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>}&#xd;&#xa;&#xa;</xsl:text>
</xsl:template>

, тогда в выводе появится новая строкагде я хочуКак будто моя таблица стилей точно потребляла одну новую строку.

Я не понимаю, что происходит, кто-то может сказать мне:

  1. Как получить желаемый результат?
  2. Что происходит с &#xa;&#xa;?

Мой процессор саксонский 9.7, если это актуально.

Ответы [ 2 ]

0 голосов
/ 03 июня 2018

Нет смысла использовать шаблон идентификации, когда вы не пытаетесь создать документ, почти идентичный вашему вводу.

Просто есть корневой шаблон, который вызывает шаблоны для применения к элементамкоторые имеют отношение к вам, таким образом, заставляя преобразование игнорировать все, что не имеет отношения к делу:

<xsl:template match="/">
  <xsl:apply-templates select="/doc/title"/>
  <xsl:apply-templates select="/doc/foo"/>
</xsl:template>

<xsl:template match="title">
  <!-- blah blah -->
</xsl:template>

<xsl:template match="foo">
  <!-- blah blah -->
</xsl:template>

Применительно к вводу xml, я получил следующее:

\section{title}
x

Значит, новая строка исчезла.

Правда?Тем не менее, мне кажется, что «\ section {title}» и «x» не находятся на одной строке, это то же самое, что сказать, что между ними была вставлена ​​новая строка.

Звучит так, как будтоВы хотите еще больше пробелов между ними, чем просто перейти на новую строку.Другими словами, вы хотите больше новых строк, чем просто ту, которую вы впервые получили.В этом случае, тогда да, имеет смысл добавить еще одну новую строку, чтобы вывод содержал еще одну новую строку.

Также обратите внимание, что &#xd; - это возврат каретки, часто используемый управляющий символв сочетании с простым символом новой строки, &#xa;, переход на новую строку обычно выполняется с помощью возврата каретки, а затем символа новой строки в Windows и соглашений о текстовых сетевых протоколах.

Однако вв наше время, и если вы производите LaTeX, возврат каретки не нужен.Вы можете просто прекратить получать его и обрабатывать новые строки, просто используя одиночные символы новой строки.

0 голосов
/ 03 июня 2018

Примечание инструкция <xsl:text>}&#xd;&#xa;</xsl:text> в вашем коде.

На самом деле он не печатает двойной перевод строки, но пара CR / LF символов, соответствующих одиночному символу новой строки в Windows.

Еще одна деталь: здесь символ CR не требуется, поскольку даже при использовании процессора XSLT под Windowsдостаточно вывести только LF char (&#xa;).

Таким образом, чтобы получить действительно двойной символ новой строки (и перед }, напишите * 1024)*.

Еще одна инструкция, которую вы должны добавить, - <xsl:strip-space elements="*"/>. Для получения подробной информации или пояснений выполните поиск в Интернете.

Что касается инструкции xsl:output, то в режиме text indent атрибут не имеет значения, вы можете удалить его.

И последний вопрос: ни шаблон, соответствующий \, ни шаблон идентификации здесь не нужны. Просто удалите их, скриптбудет короче.

Таким образом, окончательное (переработанное) содержание вашего скрипта, дающее желаемый результат, будет:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="title">
    <xsl:text>\section{</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>}&#xa;&#xa;</xsl:text>
  </xsl:template>

  <xsl:template match="foo">
    <xsl:value-of select="."/>
  </xsl:template>
</xsl:stylesheet>
...