Главная » XSLT » Трассировка потока обработки документа таблицей стилеи

0

Задача

Требуется посмотреть, как таблица стилей обрабатывала документ.

Решение XSLT 1.0

Прежде всего следует выяснить, какие возможности трассировки предостав­ляет используемый процессор XSLT. В Saxon есть флаг -t, который выводит хронометраж различных стадий обработки, и флаг -T, включающий вывод трасси­ровочной информации. В Xalan есть флаг -TT, который трассирует вызов каждого шаблона; флаг -TG трассирует каждой событие генерации; флаг -TS трассирует каждое событие отбора, а флаг -TTC – вызов дочерних шаблонов.

Если процессор вообще не поддерживает вывод трассировочной информации или вам нужен более точный контроль над выводом, то можно подумать о приме­нении xsl:message. Эта команда позволяет вывести отладочную печать для трассировки выполнения таблицы стилей. Ниже приведена служебная таблица стилей, которую вы можете импортировать для этих целей:

<!– xtrace.xslt –>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dbg="http://www.ora.com/XSLTCookbook/ns/debug">

<xsl:param name="debugOn" select="false( )"/>

<xsl:template match="node( )" mode="dbg:trace" name="dbg:xtrace"> <xsl:param name="tag" select=" ‘xtrace’ "/> <xsl:if test="$debugOn"> <xsl:message>

<xsl:value-of select="$tag"/>: <xsl:call-template name="dbg:expand-path"/> </xsl:message> </xsl:if> </xsl:template>

<!– Продлить путь xpath до текущего узла –> <xsl:template name="dbg:expand-path">

<xsl:apply-templates select="." mode="dbg:expand-path"/> </xsl:template>

<!– Корень –>

<xsl:template match="/" mode="dbg:expand-path">

<xsl:text>/</xsl:text> </xsl:template>

<!– Узел верхнего уровня –>

<xsl:template match="/*" mode="dbg:expand-path">

<xsl:text>/</xsl:text><xsl:value-of select="name( )"/> </xsl:template>

<!– Узлы, имеющие родителей –>

<xsl:template match="*/*" mode="dbg:expand-path">

<xsl:apply-templates select=".." mode="dbg:expand-path"/>/<xsl:value-of select="name( )"/>[<xsl:number/>]<xsl:text/>

</xsl:template>

<!– Узлы атрибутов –>

<xsl:template match="@*" mode="dbg:expand-path">

<xsl:apply-templates select=".." mode="dbg:expand-path"/>/@<xsl:value-of select="name( )"/> </xsl:template>

<!– Текстовые узлы (для ясности нормализованы) –> <xsl:template match="text( )" mode="dbg:expand-path">normalized- text(<xsl:value-of select="normalize-space(.)"/>)</xsl:template>

</xsl:stylesheet>

Включение в таблицу обращений к dbg:xtrace генерирует сообщения, со­держащие путь к текущему узлу. В следующем примере трассируется выполне­ние тождественного преобразования:

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

xmlns:dbg="http://www.ora.com/

XSLTCookbook/ns/debug"> <xsl:include href="xtrace.xslt"/>

<xsl:template match="/ | node( ) | @* | comment( ) | processing-instruction( )"> <xsl:call-template name="dbg:trace"/> <xsl:copy>

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

</xsl:stylesheet>

Если на вход подать такой документ:

<test foo="1">

<someElement n="1"/> <someElement n="2">

<someChild>someValue</someChild> </someElement> <someElement n="3">

<someChild>someOtherValue</someChild> </someElement> <someElement n="4">

<someChild>someValue</someChild> </someElement>

</test>

то будет выведен следующий результат:

xtrace:       /

xtrace:       /test

xtrace:       /test/@foo

xtrace:       normalized-text( )

xtrace:       /test/someElement[1]

xtrace:       /test/someElement[1]/@n

xtrace:       normalized-text( )

xtrace:       /test/someElement[2]

xtrace:       /test/someElement[2]/@n

xtrace:       normalized-text( )

xtrace:       /test/someElement[2]/someChild[1]

xtrace:       normalized-text(someValue)

xtrace:       normalized-text( )

xtrace:       normalized-text( )

xtrace:       /test/someElement[3]

xtrace:       /test/someElement[3]/@n

xtrace:       normalized-text( )

xtrace:       /test/someElement[3]/someChild[1]

xtrace:       normalized-text(someOtherValue)

xtrace:       normalized-text( )

xtrace:       normalized-text( )

xtrace:       /test/someElement[4]

xtrace:       /test/someElement[4]/@n

xtrace:       normalized-text( )

xtrace:       /test/someElement[4]/someChild[1]

xtrace:       normalized-text(someValue)

xtrace:       normalized-text( )

xtrace:       normalized-text( )

XSLT 2.0

Обращения к dbg:trace можно включать и выключать с помощью атрибута use-when точно так же, как мы поступали в случае xsl:message в рецепте 15.1, при условии, что процессор поддерживает опрос системных свойств.

В Saxon версии 8.поддерживаются дополнительные флаги трассировки:

-TJ

Включает трассировку связывания обращений к внешним Java-методам. Это бывает полезно, когда нужно понять, почему Saxon не находит метод, сопостав­ленный с функцией расширения, или выбирает конкретный метод из нескольких возможных.

-TL classname

Запускает таблицу стилей с указанным классом-получателем трассиро­вочных сообщений traceListener. Аргумент classname – имя определенного пользователем класса, который обязан реализовать интерфейс

net.sf.saxon.trace.TraceListener.

-TP

Запускает таблицу стилей с классом-получателем трассировочных сообще­ний TimedTraceListener. При этом создается выходной файл, в который запи­сывается время выполнения каждой команды. Впоследствии эту информацию можно проанализировать и построить профиль выполнения таблицы стилей.

Дополнительную информацию см. в документации по Saxon.

Обсуждение

Для достижения максимального эффекта сочетайте трассировку с отла­дочными сообщениями, показывающими, в каком месте таблицы вы сейчас на­ходитесь. Для этого можно использовать отдельные сообщения, но у утилиты xtrace есть параметр tag, который позволяет задать тег, печатаемый вместо стандартного.

В приведенной выше таблице xtrace.xslt текстовые узлы перед выводом нор­мализуются, чтобы трассировочное сообщение располагалось на одной строке. Если вы захотите видеть реальный текст, этот фильтр легко убрать.

Применяя трассировку, хорошенько подумайте, где разместить соответ­ствующие вызовы. Полезнее всего ставить их в тех местах, где происходит со­держательная обработка текущего узла. Рассмотрим таблицу стилей для обхода документа в обратном порядке, которую мы взяли из рецепта 5.5 и снабдили трас­сировкой:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dbg="http://www.ora.com/XSLTCookbook/ns/debug">

<xsl:include href="xtrace.xslt"/>

<xsl:output method="text"/>

<xsl:strip-space elements="*"/>

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

<xsl:call-template name="dbg:trace"/>

<xsl:value-of select="@name"/> <xsl:text> глава компания. </xsl:text> <xsl:call-template name="reportsTo"/> <xsl:call-template name="HimHer"/>

<xsl:text>. </xsl:text> <xsl:text>&#xa;&#xa;</xsl:text> </xsl:template>

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

<xsl:call-template name="dbg:traceM/>

<xsl:value-of select="@name"/> <xsl:text> менеджер. </xsl:text> <xsl:call-template name="reportsTo"/> <xsl:call-template name="HimHer"/> <xsl:text>. </xsl:text> <xsl:text>&#xa;&#xa;</xsl:text> </xsl:template>

<xsl:template match="employee">

<xsl:call-template name="dbg:trace"/>

<xsl:value-of select="@name"/> <xsl:text> не имеет пoдчиненныx</xsl:text> <xsl:text>. &#xa;</xsl:text> </xsl:template>

<!– Опущено … –>

</xsl:stylesheet>

Обратите внимание, что трассировка вызывается там, где выполняются какие-то действия с текущим узлом, а не просто в самом начале шаблона. При таком размеще­нии вызовов получается следующая трасса, точно отражающая порядок обхода:

xtrace:       /employee/employee[1]/employee[1]

xtrace:       /employee/employee[1]/employee[2]/employee[1]

xtrace:       /employee/employee[1]/employee[2]

xtrace:       /employee/employee[1]

xtrace:       /employee/employee[2]/employee[1]

xtrace:       /employee/employee[2]/employee[2]/employee[1]

xtrace:       /employee/employee[2]/employee[2]/employee[2]

xtrace:       /employee/employee[2]/employee[2]/employee[3]

xtrace:       /employee/employee[2]/employee[2]

xtrace:       /employee/employee[2]

xtrace:       /employee/employee[3]/employee[1]/employee[1]

xtrace:       /employee/employee[3]/employee[1]/employee[2]

xtrace:       /employee/employee[3]/employee[1]/employee[3]

xtrace:       /employee/employee[3]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[1]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[2]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[2]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[3]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[3]

xtrace:       /employee/employee[3]/employee[2]

xtrace:       /employee/employee[3]

xtrace:       /employee

Если поставить обращения к трассировке в начало шаблона, то трасса будет отражать обход в прямом порядке, что лишь сбивает с толку:

xtrace:       /employee

xtrace:       /employee/employee[1]

xtrace:       /employee/employee[1]/employee[1]

xtrace:       /employee/employee[1]/employee[2]

xtrace:       /employee/employee[1]/employee[2]/employee[1]

xtrace:       /employee/employee[1]/employee[2]

xtrace:       /employee/employee[1]

xtrace:       /employee/employee[2]

xtrace:       /employee/employee[2]/employee[1]

xtrace:       /employee/employee[2]/employee[2]

xtrace:       /employee/employee[2]/employee[2]/employee[1]

xtrace:       /employee/employee[2]/employee[2]/employee[2]

xtrace:       /employee/employee[2]/employee[2]/employee[3]

xtrace:       /employee/employee[2]/employee[2]

xtrace:       /employee/employee[2]

xtrace:       /employee/employee[3]

xtrace:       /employee/employee[3]/employee[1]

xtrace:       /employee/employee[3]/employee[1]/employee[1]

xtrace:       /employee/employee[3]/employee[1]/employee[2]

xtrace:       /employee/employee[3]/employee[1]/employee[3]

xtrace:       /employee/employee[3]/employee[1]

xtrace:       /employee/employee[3]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[1]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[2]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[2]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[2]

xtrace:       /employee/employee[3]/employee[2]/employee[3]

xtrace:       /employee/employee[3]/employee[2]/employee[3]/employee[1]

xtrace:       /employee/employee[3]/employee[2]/employee[3]

xtrace: /employee/employee[3]/employee[2]

xtrace: /employee/employee[3]

См. также

catchXSL! (http://www.xslprofiler.org/overview.html) – бесплатный инструмент для профилирования XSL-преобразований способом, зависящим от процессора. В процессе преобразования все команды XSLT протоколируются в виде события стиля, снабженного временным штампом. Собранная статистика дает информацию о ходе преобразования и позволяет понять, в каких местах таблицу стилей можно было бы улучшить. В подробном отчете приводится информация о каждом шаге и затраченном на него времени. Отчет в разрезе шаблонов показывает время, прове­денное в каждом шаблоне, и тем самым дает возможность отыскать узкие места.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии