#xml #xslt #saxon #xslt-3.0
Вопрос:
Мне нужно запустить выходной файл, созданный XSLT (XHTML), в техническом тестовом стенде.
Каждый раз, когда я использую длинную текстовую строку (из исходного файла) и выполняю XSLT, тестовая среда не утверждает документ. Похоже, причина в том, что выходной файл (XHTML) принимает длинную текстовую строку и разбивает ее на несколько строк.
В «xsl:вывод» я установил атрибут «подавить отступ», но похоже, что атрибут управляет только отступом элементов узла (тегов), а не длиной значений узлов.
В моей среде я также управлял выходным файлом в терминале, чтобы убедиться, что проблема не только изолирована от моего текстового редактора программирования.
Есть ли способ контролировать длину, когда XSLT решит разрезать длинную строку на несколько строк?
Мое окружение:
- Саксонский-ОН 10,5 Дж из Саксоники
- Версия Java 11.0.11
Вы можете увидеть поведение в xsltfiddle: https://xsltfiddle.liberty-development.net/jxWZS72/4
Данные:
<?xml version="1.0" encoding="utf-8" ?>
<data>
<content-cut>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</content-cut>
<content-no-cut>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt</content-no-cut>
</data>
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
>
<xsl:output method="xhtml" indent="yes" suppress-indentation="content" html-version="5"/>
<xsl:template match="data">
<html>
<head>
<title>MyTitle</title>
</head>
<body>
<string-one>
<xsl:value-of select="content-cut"/>
</string-one>
<string-two>
<xsl:value-of select="content-no-cut"/>
</string-two>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Результат:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MyTitle</title></head>
<body>
<string-one>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
</string-one>
<string-two>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt</string-two>
</body>
</html>
Желаемый результат:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MyTitle</title></head>
<body>
<string-one>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </string-one>
<string-two>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt</string-two>
</body>
</html>
Комментарии:
1. Известно, что Saxon вставляет разрывы строк в абзацы для удобства чтения, если вы используете отступы, я думаю, что коммерческие издания обладают собственным свойством вывода, чтобы теоретически включить это, установив очень большую длину строки по умолчанию. Я не помню, есть ли простое решение для НЕГО; и полагаться на отступ, с одной стороны, при сохранении определенного форматирования, с другой стороны, является сложным подходом.
2. saxonica.com/html/documentation10/extensions/output-extras/… имеет
saxon:line-length
значение по умолчанию80
и «При использовании метода вывода HTML текстовые строки разделяются на эту длину строки, когда это возможно»..3. Спецификация w3.org/TR/xslt-xquery-serialization-31/#HTML_INDENT предполагает, что, например, для
pre
элемента внутри содержимого не следует добавлять пробелы, и я думаю, что Саксон уважает это, так что, возможно, в любом случае, какstring-one
string-two
и любой HTML-элемент или нет, используйтеpre
вместо этого. Я думаю, что техническиsuppress-indentation="string-one string-two"
это тоже должно сработать, но давайте посмотрим, что скажет Майкл Кей.
Ответ №1:
Похоже, что ваш «тестовый стенд» полагается на поведение, которое не требуется спецификацией XSLT и, вероятно, не требуется реальным приложением. В таких ситуациях наилучшим подходом, как правило, является смягчение требований испытательного стенда, чтобы он не предъявлял необоснованных требований к выходу преобразования.
Тестирование сериализованного вывода XML в любом случае всегда сложно, особенно когда indent="yes"
он задан, что делает многие аспекты реализации вывода определенными.
Вы используете suppress-indentation="content"
, но у вас нет элемента, вызываемого content
в сериализованном выводе. Вы пробовали » подавить отступ=»строка-одна строка-две»? Я думаю, что это должно работать в соответствии со спецификацией; если нет, мы, вероятно, должны это исправить.
Но я думаю, что вам, вероятно, следует пересмотреть то, как вы проводите тестирование. Сравнение сериализованных выходных данных с отступами слишком хрупко для комфорта.
Комментарии:
1. Я обновил вопрос, обновив xsltfiddle с соответствующим значением в «подавить отступ». Это конкретное изменение не улучшило результат. Я согласен, что сочетание отступа=»да» с необходимостью избегать сокращения длинных строк в значениях элементов приводит к ошибкам и нестабильности. — Однако в данном конкретном случае испытательный стенд находится вне зоны моей досягаемости, поэтому я не могу его «расслабить». Однако было бы полезно, чтобы тестовые варианты могли контролировать и регулировать максимально допустимую ширину текста для значений элементов.
2. Кажется немного странным, что я могу автоматически производить ок. 10 000 строк XHTML и единственная текущая нерешенная проблема, которая не позволяет выполнить это преобразование на 100% автоматически, — это разделение строк. Обратите внимание, что я высоко ценю ваше время, потраченное на предоставление ответов и комментариев.
3. Я должен был добавить ссылку на саксонский вопрос, поднятый по этому поводу: saxonica.plan.io/issues/5018
Ответ №2:
Я написал тестовый случай
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:param name="suppress-indentation-in" as="xs:string*" static="yes" select="'p', 'string-data'"/>
<xsl:param name="test-elements" as="xs:string*" static="yes" select="'div', $suppress-indentation-in, 'pre', 'span',"/>
<xsl:output method="html" indent="yes" html-version="5.0" _suppress-indentation="{$suppress-indentation-in}"/>
<xsl:mode on-multiple-match="use-last"/>
<xsl:template match="/">
<html>
<head>
<title>suppress-indenation test in {$suppress-indentation-in}</title>
</head>
<body>
<h1 data-suppress-indentation-in="{$suppress-indentation-in}">suppress-indentation test in {$suppress-indentation-in}</h1>
<xsl:iterate select="$test-elements">
<xsl:param name="root" select="*"/>
<section>
<h2>{.}</h2>
<xsl:element name="{.}">{$root}</xsl:element>
</section>
</xsl:iterate>
</body>
</html>
</xsl:template>
<xsl:template match="/" name="xsl:initial-template">
<xsl:next-match/>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
</xsl:stylesheet>
чтобы запустить его на основе входных данных, взятых из вашего образца
<text>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</text>
и даже с Saxon 10.5 результат показывает suppress-indentation
, что он не учитывается при выводе
<!DOCTYPE HTML><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>suppress-indenation test in p string-data</title>
</head>
<body>
<h1 data-suppress-indentation-in="p string-data">suppress-indentation test in p string-data</h1>
<section>
<h2>div</h2>
<div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
</section>
<section>
<h2>p</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</section>
<section>
<h2>string-data</h2>
<string-data>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.</string-data>
</section>
<section>
<h2>pre</h2>
<pre>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</pre>
</section>
<section>
<h2>span</h2><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.</span></section>
</body>
</html><!--Run with SAXON HE 10.5.1 -->
Как https://www.w3.org/TR/xslt-xquery-serialization-31/#HTML_INDENT говорит:
Символы пробела НЕ ДОЛЖНЫ добавляться в содержимое элемента, чье расширенное имя Q совпадает с членом списка расширенных имен Q в значении параметра подавления отступов
Я думаю, что у Saxon до 10.5 есть ошибка здесь: https://saxonica.plan.io/issues/5018.
Единственным обходным путем, по-видимому, является использование pre
элемента.
Ошибка https://saxonica.plan.io/issues/5018 однако это было исправлено, и последняя версия 10.6 теперь поддерживает suppress-indentation
просто отлично.
Комментарии:
1. Я протестировал упаковку с предварительными тегами. Он работает в xsltfiddle и создает выходной файл (XHTML) в моей среде. Управление выходным файлом в веб-браузере приводит к тому, что тестовая строка в два раза шире документа. Вероятно, это нормально из-за использования предварительных тегов, но ширина текстовой строки не совпадает с остальной частью документа. Без предварительного тега интернет-браузер может получить очень длинную текстовую строку в формате XHTML и выяснить, как представить документ с правильной шириной вырезанной строки. Таким образом, предварительный тег не работает в качестве обходного пути. В качестве временного решения я установил отступ «нет».
2. @Toolbox, ну, я предложил
pre
элемент только тогда, когда вы, казалось, смотрели на вывод Saxon, и только дляpre
Saxon, похоже, не соблюдается разрыв строки с HE. Если рендеринг в браузере также является целью, я бы предложил второй шаг преобразования. В противном случае вам нужно использовать CSS, чтобыpre
содержимое выглядело «нормально»:<pre style="white-space: pre-wrap; font-style: normal; font-family: serif;">
.3. Да, я забыл объяснить, что конечным результатом является документ, который пользователь может видеть в интернет-браузере.