Написание эффективных 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. Он очень краток и прост в использовании. Просто передать параметры шаблону. Этот метод называется инкапсуляцией и является одним из оснований хорошего программирования.