Написание эффективных XSLT
Каковы принципы и шаблоны, которые вписываются в эффективный XSLT?
Когда я говорю "эффективный", я имею в виду, что это
- Хорошо структурированный и читаемый
- Простой, лаконичный
- Эффективный (т.е. имеет хорошую производительность)
Короче говоря, я ищу лучшие практики для XSLT.
Я уже видел вопрос об эффективности, но эффективный код теряет свою ценность, если вы не можете понять, что он делает.
Ответы
Ответ 1
Я думаю, что хороший способ ответить на этот вопрос должен приблизиться к нему с другой стороны. Какие методы делают XSLT неэффективным и почему?
Некоторые из вещей, которые я видел, приводят к неэффективному XSLT:
-
Использование for-each
. Все говорили это; Я говорю это снова. Я нахожу, что for-each
часто является признаком разработчика, пытающегося использовать традиционные методы программирования на декларативном языке.
-
Недоиспользование XPath. Много плохого XSLT, которое я видел, существует исключительно потому, что разработчик не понял предикатов, спецификаторов осей, position()
и current()
, и поэтому он реализовал логику с использованием конструкций XSLT.
-
Недоиспользование метаданных. Иногда вы можете устранить огромное количество XSLT, предоставив свое преобразование метаданными.
-
Недостаточная предварительная обработка.. Если, например, XML-документ содержит данные, которые необходимо проанализировать с помощью манипуляции с строкой XSLT, часто гораздо проще выполнять весь анализ за пределами XSLT и либо добавить анализируемые результаты в XML, либо передать анализируемые результаты в качестве аргумента преобразования. Я видел замечательную непостижимую XSLT-реализацию бизнес-логики, которая была бы тривиальной для реализации на С# или Python.
Самая большая проблема, с которой я сталкиваюсь в своем собственном мире XSLT (у меня есть несколько более 3000 линейных преобразований, которые я поддерживаю) - это мертвый код. Я уверен, что в моих преобразованиях есть шаблоны, которые никогда не будут использоваться снова, потому что условия, которые они тестируют, больше никогда не появятся. Нет никакого способа определить программно, если что-то вроде <xsl:template match="SomeField[contains(., "some value")]>
живое или мертвое, потому что оно зависит от того, что метаданные не могут вам сказать.
Ответ 2
I. Элегантный XSLT-код
Часто можно найти примеры красивого кода XSLT, особенно когда XSLT используется как язык функционального программирования.
Примеры см. в этой статье на FXSL 2.0 - библиотека функционального программирования для XSLT 2.0.
В качестве языка FP XSLT также является декларативным языком. Это, между прочим, означает, что объявляется, определяет существующие отношения.
Такое определение часто не нуждается в дополнительном коде для создания результата - оно само является его собственной реализацией или исполняемым определением или исполняемой спецификацией.
Вот небольшой пример.
Это выражение XPath 2.0 определяет "Максимальный Prime Factor натурального числа ":
if(f:isPrime($pNum))
then $pNum
else
for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
$vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
$vDiv2 in $pNum idiv $vDiv1
return
max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
Чтобы произнести его на английском языке, максимальный простой коэффициент числа pNum
- это само число, если pNum
в противном случае, если vDiv1
и vDiv2
являются двумя факторами pNum
, тогда максимальный простой коэффициент pNum
- это больший из максимальных простых коэффициентов vDiv1
и vDiv2
.
Как мы используем это для фактического вычисления Максимального основного фактора в XSLT? Мы просто завершаем определение выше в <xsl:function>
и... получаем результат!
<xsl:function name="f:maxPrimeFactor" as="xs:integer">
<xsl:param name="pNum" as="xs:integer"/>
<xsl:sequence select=
"if(f:isPrime($pNum))
then $pNum
else
for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
$vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
$vDiv2 in $pNum idiv $vDiv1
return
max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
"/>
</xsl:function>
Таким образом, мы можем вычислить MPF для любого натурального числа, например:
f:maxPrimeFactor(600851475143)
= 6857
Что касается эффективности, ну, это преобразование занимает всего 0,109 сек.
Другие примеры как ellegant, так и эффективного кода XSLT:
II. Некоторые правила
Вот несколько правил написания "качественного XSLT-кода", взятого из Блог Mukul Ghandi.
Их можно проверить/выполнить с помощью инструмента разработанного Мукулом:
-
DontUseDoubleSlashOperatorNearRoot: избегайте использования оператора//рядом с корнем большого дерева.
-
DontUseDoubleSlashOperator: избегайте использования оператора//в выражениях XPath.
-
SettingValueOfVariableIncorrectly: присвойте значение переменной, используя синтаксис "select", если назначить строковое значение.
-
EmptyContentInInstructions: не используйте пустое содержимое для инструкций, таких как xsl: for-each '' xsl: if '' xsl: when 'и т.д.
-
DontUseNodeSetExtension: не используйте функцию расширения node -set при использовании XSLT 2.0.
-
RedundantNamespaceDeclarations: в элементе xsl: stylesheet имеются избыточные объявления пространства имен.
-
UnusedFunction: функции стилей не используются.
-
UnusedNamedTemplate: Именованные шаблоны в таблице стилей не используются.
-
UnusedVariable: переменная не используется в таблице стилей.
-
UnusedFunctionTemplateParameter: параметр функции или шаблона не используется в теге function/template.
-
TooManySmallTemplates: Слишком много низкоуровневых шаблонов в таблице стилей (10 или более).
-
MonolithicDesign: использование одного шаблона/функции в таблице стилей. Вы можете модулировать код.
-
OutputMethodXml: использование метода вывода 'xml' при генерации HTML-кода.
-
NotUsingSchemaTypes: таблица стилей не использует ни один из встроенных типов схем (xs: string и т.д.) при работе в режиме XSLT 2.0.
-
ИспользованиеNameOrLocalNameFunction: Использование функции name(), когда local-name() может быть подходящим (и наоборот).
-
FunctionTemplateComplexity: размер или сложность функции или шаблона высока. Существует необходимость в рефакторинге кода.
-
NullOutputFromStylesheet: таблица стилей не генерирует полезных результатов. Пожалуйста, переустановите логику стилей.
-
ИспользованиеNamespaceAxis: использование устаревшей оси пространства имен при работе в режиме XSLT 2.0.
-
CanUseAbbreviatedAxisSpecifier: использование длинных спецификаторов оси, таких как child::, attribute:: или parent:: node().
-
UsingDisableOutputEscaping: установите для атрибута disable-output-escaping значение "yes". Пожалуйста, передумайте логику стилей.
-
NotCreatingElementCorrectly: Создание элемента node с помощью инструкции xsl: element, когда возможно было возможно напрямую.
-
AreYouConfusingVariableAndNode: вы можете ввести в заблуждение ссылку на переменную с помощью ссылки node. (внесенный Ален Бенедетти)
-
IncorrectUseOfBooleanConstants: неверно использовать логические константы как 'true' или 'false'. (внесенный Тони Лавинио)
-
ShortNames: использование имени одного символа для переменной/функции/шаблона. Используйте значащие имена для этих функций.
-
NameStartsWithNumeric: имя переменной/функции/шаблона начинается с числового символа
Ответ 3
Лучшая практика 1: использовать шаблоны вместо < xsl: for-each > , когда вы можете (что составляет 99% случаев)
(могу ли я добавить ПОДДЕРЖКУ как дополнительный ингредиент в лучших практиках, imho даже самый важный)
Для понимания xsl вам действительно нужно немного практики.
Не понимаю, что такое. делает очень относительный, конечно.
Это для dSL для XSLT, поскольку конструкция xsl: for-each имеет тенденцию быть
для новичков, но на самом деле
- менее структурированный,
- менее простой,
- менее кратким и
- гораздо менее ремонтопригодный
чем шаблоны, и только
- equaly readable (в лучшем случае!!) для этого. с минимальным опытом работы с шаблонами.
НИКОГДА, НИКОГДА ИСПОЛЬЗУЙТЕ < xsl: for-each > ELEMENT!
Я признаю, что название несколько преувеличены, существуют, я был сказали, случаи, когда "xsl для каждого" может иметь это значение, но эти случаи очень, очень редко.
Мне приходилось придумывать довольно сложный клиентский сайт xml/xslt в менее чем за неделю, и использовали для каждого элемента по всему месту. Теперь, несколько лет спустя и, вроде, мудрее, я потратил свое время и переписал начальный код, используя только шаблоны. Теперь код намного чище и более адаптируемым.
Либо вы знаете это, либо либо вы должен: < xsl: template > и < XSL: apply-templates > почти всегда путь. Если вы xsl-ing, и вы не полностью понимают эти теги, прекратите свою работу, изучите их, получите aha-erlebnis, и продолжите свою работу как возрожденный (wo) человек.
Ответ 4
Проблемы с файлами
1. Много мелких файлов лучше, чем несколько больших.
Разделите hamburger.xsl на i-bread.xsl и i-beef.xsl.
2. Префикс включал/импортировал файлы с помощью "i -.
Он служит индикатором того, что файл shoud можно редактировать с осторожностью, так как вы можете нарушить функциональность импорта/включения файлов. Проверьте их перед внесением изменений.
3. Никогда не включайте/импортируйте неподписанный файл.
Если вы хотите сделать чизбургер .xsl, не включайте hamburger.xsl. Вместо этого включите i-bread.xsl, i-beef.xsl и новый i-cheese.xsl.
Ответ 5
Для удобства чтения я использую тег xsl:template
. Он очень краток и прост в использовании. Просто передать параметры шаблону. Этот метод называется инкапсуляцией и является одним из оснований хорошего программирования.