2014-02-20 2 views
3

Мне нужна информация для оптимизации моего xslt.Оптимизация xslt: доступ к дочернему многократному времени или переменная использования

В моем шаблоне я получить доступ к ребенку несколько раз, как, например:

<xsl:template match="user"> 
<h1><xsl:value-of select="address/country"/></h1> 
<p><xsl:value-of select="address/country"/></p> 
<p><xsl:value-of select="address/country"/></p> 
    ... more and more... 
<p><xsl:value-of select="address/country"/></p> 
</xsl:template> 

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

<xsl:template match="user"> 
<xsl:variable name="country" select="address/country"/> 
<h1><xsl:value-of select="$country"/></h1> 
<p><xsl:value-of select="$country"/></p> 
<p><xsl:value-of select="$country"/></p> 
    ... more and more... 
<p><xsl:value-of select="$country"/></p> 
</xsl:template> 

Или использование переменной потребляет больше ресурсов, чем разведение дерева несколько раз?

ответ

4

Обычно XML-файл анализируется как целое и хранится в памяти как XDM. Таким образом, я предполагаю, что

, чем разбор дереву несколько раз

вы на самом деле имели в виде доступа к внутреннему представлению нескольких раз входных XML. На приведенном ниже рисунке это, мы говорим о исходном дереве:

enter image description here
(взято из Майкла Кея XSLT 2.0 и XPath 2.0 программист Справочник, стр 43)

Аналогично , xsl:variable создает узел (или, точнее, временный документ), который хранится в памяти и к которому также необходимо получить доступ.

Теперь, что именно вы подразумеваете под оптимизацией? Вы имеете в виду время, необходимое для выполнения преобразования или использования процессора и памяти (как вы упоминаете «ресурсы» в своем вопросе)?

Кроме того, производительность зависит от реализации вашего процессора XSLT, конечно. Единственный надежный способ выяснить - на самом деле тест.

Напишите две таблицы стилей, которые отличаются только в этом отношении, то есть идентичны в противном случае. Затем пусть оба из них преобразуют один и тот же входной XML и измеряют время, которое они принимают.

Я предполагаю, что доступ к переменной происходит быстрее, и также удобнее повторять имя переменной, чем повторять полные пути при написании кода (это иногда называют «удобными переменными»).


EDIT: Заменено-то более подходящее, в качестве ответа на ваш комментарий.

Если вы на самом деле проверить это, написать две таблицы стилей:

STYLESHEET с переменной

<?xml version="1.0" encoding="utf-8"?> 

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/root"> 
     <xsl:copy> 
     <xsl:variable name="var" select="node/subnode"/> 
     <subnode nr="1"> 
      <xsl:value-of select="$var"/> 
     </subnode> 
     <subnode nr="2"> 
      <xsl:value-of select="$var"/> 
     </subnode> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

стилей без переменной

<?xml version="1.0" encoding="utf-8"?> 

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/root"> 
     <xsl:copy> 
     <subnode nr="1"> 
      <xsl:value-of select="node/subnode"/> 
     </subnode> 
     <subnode nr="2"> 
      <xsl:value-of select="node/subnode"/> 
     </subnode> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

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

<root> 
    <node> 
     <subnode>helloworld</subnode> 
    </node> 
</root> 

EDIT: Как было предложено @Michael Кей, я измерил среднее время в 100 пробегов ("-t и -repeat: 100 в командной строке Saxon"):

with variable: 9 ms 
without variable: 9 ms 

Этот не означает, что результат совпадает с вашим XSLT-процессором.

+0

Thx для вашего ответа. Под «Оптимизацией» я имел в виду и то и другое: время выполнения преобразования и использование памяти. Сначала я хотел удалить переменные, чтобы избежать хранения контента, который я могу легко достичь. Но потом я спрашивал меня, удалят ли переменные время, необходимое для трансформации (если да, я этого не сделаю). Что касается второй части вашего ответа: этот случай является фиктивным примером для объяснения моей проблемы. На самом деле мой шаблон намного сложнее. Узел «страна» используется в сочетании с другими элементами, и нет никаких преимуществ для его размещения в определенном шаблоне. – ylerjen

+0

Добро пожаловать. Я предположил, что это всего лишь образец: «Я полагаю, что это образец шаблона XSLT». Тем не менее, вы точно знаете, как только вы на самом деле измерили производительность. –

+0

@ Miam84 Я редактировал мой вопрос, чтобы сделать его более информативным. Пожалуйста, смотрите. –

1

Редактировать: Будучи приглашенным для переоценки моего ответа, я узнал, что ваше собственное предложение, вероятно, вполне подходит для вас. Если вы не инкапсулируете значение переменной selection в дополнительные одинарные кавычки [чтобы сделать его строковой константой], он будет содержать выбранный элемент. [Вместо того, чтобы вставлять текстовое содержимое указанного элемента, вы можете даже скопировать весь подэлемент выбранного элемента, используя<xsl:copy-of select="$country"/>, если вы этого хотите.]

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

<xsl:apply-template select="address/country"/> 
[...] 
<xsl:template match="address/country"> 
    <h1><xsl:value-of select="."/></h1> 
    <p><xsl:value-of select="."/></p> 
    [...] 
</xsl:template> 

Как @ Mathias_Müller suggested, есть также способы выразить свои "... больше и далее ... «Поведение без необходимости копировать« вставлять »соответствующие строки снова и снова. XSLT 2.0 интерпретирует числовые диапазоны в for-each заявлении:

<xsl:for-each select="1 to 100"> 
    <p><xsl:value-of select="."/></p> 
</xsl:for-each> 

Если XSLT не доступна в версии> = 2.0, немного более сложное решение является условно назвать шаблоны явным образом с помощью call-template при прохождении параметров и реализации разрыва и-властвуй подход [для защиты стека]:

<xsl:call-template name="ntimes"> 
    <xsl:with-param name="counter" select="100"/> 
</xsl:call-template> 
[...] 
<xsl:template name="ntimes"> 
    <xsl:param name="counter" select="0"/> 
    <xsl:if test="$counter > 0"> 
    <xsl:choose> 
     <xsl:when test="$counter = 1"> 
     <xsl:apply-template select="address/country"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:variable name="half" select="floor($counter div 2)"/> 
     <xsl:call-template name="ntimes"> 
      <xsl:with-param name="counter" select="$half"/> 
     </xsl:call-template> 
     <xsl:call-template name="ntimes"> 
      <xsl:with-param name="counter" select="$counter - $half"/> 
     </xsl:call-template> 
     [...] 

Go here и here для объяснения.

Если честно, я ничего не знаю о производительности и оптимизации в XSLT. Я никогда не считал, что это стоит усилий, учитывая, что большую часть времени я использую XSLT-процессоры, написанные на Java, и о том, что использовать большие входные файлы, в то время как theres все еще целых, несколько сотен МБ ОЗУ, потребляющих JVM для запуска до ..?

+1

Не совсем, это _is_ содержимое 'address/country', которое хранится как содержимое переменной. Наличие '' inside 'xsl: variable' - это просто код с тем же концом. –

2

Для всех вопросов производительности ответ: это зависит.

  • Это зависит от того, какой процессор XSLT вы используете, и о его оптимизации.

  • Скорее всего, это зависит от того, сколько детей нужно искать, чтобы найти те, которые вы ищете.

Единственный способ узнать это - измерить его и измерить его очень тщательно.

Лично я бы использовал переменную, если был задействован сложный предикат, но не если я просто ищу детей по имени.

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

Смежные вопросы