Xpoint
   [напомнить пароль]

Упрощение XPath выражений с помощью ключей

Упрощение XPath выражений с помощью ключей

Ключи в xsl можно использовать не только для группировки Мюнха. С их помощью можно упростить XPath выражения и зачастую уменьшить время преобразования.

Предположим мы хотим выводить список новых закладок из delicious c определенным тегом (http://del.icio.us/tag/javascript).
У delicious есть RSS поток последних пополнений http://del.icio.us/rss/

Задачу можно решить 2-мя разными способами: выбрав узлы, удовлетворяющие паттерну или узлы с указанным значением ключа.
В xsl-процессоре libxsl есть режим, позволяющий посмотреть время наложения каждого шаблона. Так что в конце можно будет сравнить два решения не только с эстетической точки зрения, но и с точки зрения производительности.

Поехали:
Объявляем необходимые пространства имен.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
xmlns:d="http://purl.org/rss/1.0/"
>

Результат мы хотим получить в виде текста

<xsl:output method="text"/>

Вызваем шаблоны для элемента rdf:RDF с разными mode. Очевидно, что результат работы у них должен быть одинаковый.

<xsl:template match="/">
  <xsl:apply-templates select="rdf:RDF" mode="key"/>
  -----
  <xsl:apply-templates select="rdf:RDF" mode="string"/>
</xsl:template>

Первый варинат: выбираем те элементы item, которые удовлетворяют паттерну.

<xsl:template match="rdf:RDF" mode="string">
  <xsl:apply-templates select="d:item[taxo:topics / rdf:Bag / rdf:li / @resource = 'http://del.icio.us/tag/javascript']"/>
</xsl:template>

Второй вариант: создаем ключ. Ключ - значение элемента item/taxo:topics/rdf:Bag/rdf:li/@resource, значение - узел item

<xsl:key name="tag" match="d:item" use="taxo:topics / rdf:Bag / rdf:li / @resource"/>

Выбираем узлы, где значение ключа равено http://del.icio.us/tag/javascript:

<xsl:template match="rdf:RDF" mode="key">
  <xsl:apply-templates select="key('tag', 'http://del.icio.us/tag/javascript')"/>
</xsl:template>
<xsl:template match="d:item">
  <xsl:value-of select="d:title"/>
</xsl:template>

Смотрим производительность (xml, xslt):
xsltproc --noout --profile index.xsl index.xml

matchnamemodeCallsTot 100usAvg
rdf:RDFstring13434
d:item6111
rdf:RDFkey166
/133

Первый шаблон (mode="string") выполняется в 6 раз дольше второго (mode="key"). Однако, эти цифры не учитывают время на создание ключа. Про время создания ключа напишу чуть позже :)

Плюсы использования ключей:

  • уменьшения времени преобразования.
  • xsl легче модифицировать, если поменялись данные. XPath надо будет поменять всего в одном месте. Это не очевидно из приведенного примера, но вообразите ситуацию, когда один ключ используется раз 10.
  • результат работы функции key() не зависит, в пределах одного документа, от контекста, в котором ее вызвали. Это удобно при перегруппировке сильно разветвленных деревьев.

Приложения

XML к статье
XSLT к статье

Powered by POEM™ Engine Copyright © 2002-2005