Чтение онлайн

на главную - закладки

Жанры

Технология XSLT

Валиков Алексей Н.

Шрифт:

</items>

Пусть входящий документ представляет собой список объектов (элементов

item
), каждый из которых имеет имя (атрибут
name
) и источник (атрибут
source
). Требуется сгруппировать объекты по своим источникам и получить документ приблизительно следующего вида.

Листинг 8.20. Требуемый результат

<sources>

 <source name="a">

<item source="a" name="A"/>

<item source="a" name="C"/>

<item source="a" name="H"/>

 </source>

 <source name="b">

<item source="b" name="B"/>

<item source="b" name="E"/>

<item source="b" name="F"/>

 </source>

 <source name="c">

<item source="c" name="D"/>

<item source="c" name="G"/>

 </source>

</sources>

Первым

шагом на пути решения этой задачи является формулировка в терминах XSLT предложения "сгруппировать объекты по своим источникам". Источник каждого объекта определяется его атрибутом
source
, значит множество объектов, принадлежащих одному источнику
"а"
, будет определяться путем выборки

/items/item[@source='a']

Тогда для каждого элемента

item
в его группу войдут элементы, которые будут выбраны выражением

/items/item[@source=current/@source]

Попробуем использовать этот факт в следующем шаблоне:

<xsl:template match="item">

 <source name="{@source}">

<xsl:copy-of select="/items/item[@source=current/@source]"/>

 </source>

</xsl:template>

Как и ожидалось, при применении этого правила к элементам

item
для каждого из них будет создана группа, принадлежащая тому же источнику, — уже хороший результат, но в условии требуется создать по группе не для каждого объекта, а для каждого источника. Чтобы достичь этого, можно создавать группу только для первого объекта, принадлежащего ей. Провести такую проверку опять же несложно: объект будет первым в группе тогда и только тогда, когда ему не предшествуют другие, элементы
item
, принадлежащие тому же источнику. Иначе говоря, создаем группы только для тех элементов, для которых выражение

preceding-sibling::item[@source-current/@source]

будет возвращать пустое множество.

С небольшими добавлениями искомое преобразование целиком будет иметь вид.

Листинг 8.21. Преобразование

<xsl:stylesheet

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="items">

<sources>

<xsl:apply-templates/>

</sources>

 </xsl:template>

 <xsl:template match="item">

<xsl:choose>

<xsl:when

test="preceding-sibling::item[@source=current/@source]"/>

<xsl:otherwise>

<source name="{@source}">

<xsl:copy-of select="self::node

|following-sibling::item[@source=current/@source]"/>

</source>

</xsl:otherwise>

</xsl:choose>

 </xsl:template>

</xsl:stylesheet>

Бесспорно,

решение было несложным, но довольно громоздким. Самым же узким местом в этом преобразовании является обращение к элементам
item
источника текущего элемента посредством сравнения атрибутов
source
.

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

item
, но представьте себе ситуацию, когда элементов действительно много.

Проблема, которую мы подняли, достаточно серьезна. Она состоит в оптимизации поиска узлов с определенными свойствами в древовидно организованной структуре.

Попробуем разобраться в смысле фразы "узел обладает определенными свойствами". Очевидно, это означает, что для этого узла выполняется некое логическое условие, иначе говоря, некий предикат обращается в "истину".

Однако какого именно типа условия мы чаще всего проверяем? Анализируя различные классы задач, можно придти к выводу, что в большинстве случаев предикаты являются равенствами — выражениями, которые обращаются в "истину" тогда и только тогда, когда некоторый параметр узла, не зависящий от текущего контекста, равен определенному значению. В нашем примере смысл предиката на самом деле состоит не в том, чтобы проверить на истинность выражение

@source=current/@source
, а в том, чтобы проверить на равенство
@source
и
current/@source
.

Если переформулировать это для общего случая, то нам нужно выбрать не те узлы, для которых истинно выражение

A=B
, скорее нужно выбрать те, для которых значение
A
равно значению
B
. Иначе говоря, узел будет идентифицироваться значением в своего свойства
A
. И если мы заранее вычислим значения свойств
A
, проблема поиска узлов в дереве сведется к классической проблеме поиска элементов множества (в нашем случае — узлов дерева) по определенным значениям ключей (в нашем случае — значениями свойств
A
).

Поделиться:
Популярные книги

Потомок бога

Решетов Евгений Валерьевич
1. Локки
Фантастика:
попаданцы
альтернативная история
аниме
сказочная фантастика
5.00
рейтинг книги
Потомок бога

Я все еще князь. Книга XXI

Дрейк Сириус
21. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще князь. Книга XXI

Лучший из худших-2

Дашко Дмитрий Николаевич
2. Лучший из худших
Фантастика:
фэнтези
5.00
рейтинг книги
Лучший из худших-2

Хозяйка забытой усадьбы

Воронцова Александра
5. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка забытой усадьбы

Ну привет, заучка...

Зайцева Мария
Любовные романы:
эро литература
короткие любовные романы
8.30
рейтинг книги
Ну привет, заучка...

Я тебя верну

Вечная Ольга
2. Сага о подсолнухах
Любовные романы:
современные любовные романы
эро литература
5.50
рейтинг книги
Я тебя верну

Новый Рал 2

Северный Лис
2. Рал!
Фантастика:
фэнтези
7.62
рейтинг книги
Новый Рал 2

Стеллар. Трибут

Прокофьев Роман Юрьевич
2. Стеллар
Фантастика:
боевая фантастика
рпг
8.75
рейтинг книги
Стеллар. Трибут

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Чапаев и пустота

Пелевин Виктор Олегович
Проза:
современная проза
8.39
рейтинг книги
Чапаев и пустота

Вы не прошли собеседование

Олешкевич Надежда
1. Укротить миллионера
Любовные романы:
короткие любовные романы
5.00
рейтинг книги
Вы не прошли собеседование

Идеальный мир для Лекаря 15

Сапфир Олег
15. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 15

Возвышение Меркурия. Книга 14

Кронос Александр
14. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 14

Кто ты, моя королева

Островская Ольга
Любовные романы:
любовно-фантастические романы
7.67
рейтинг книги
Кто ты, моя королева