#xml #xslt
#xml #xslt
Вопрос:
Эй, ребята, я хочу создать мини-расписание для зоопарка.
Ниже приведен макет функциональности ms paint. Что я ищу, так это список периодов времени по горизонтали вверху, и когда вы нажимаете на один из них, страница перемещается вниз к этому временному интервалу и показывает его детали.
Точно так же, как теги-привязки в HTML, и мои данные хранятся в XML.
Итак, вот мои XML-данные:
<zoo>
<animal name="Lion">
<feeding-time>11:00</feeding-time>
</animal>
<animal name="Penguin">
<feeding-time>14:00</feeding-time>
</animal>
<animal name="Elephant">
<feeding-time>9:00</feeding-time>
</animal>
<animal name="Tortoise">
<feeding-time>11:00</feeding-time>
</animal>
<animal name="Ape">
<feeding-time>16:00</feeding-time>
</animal>
<animal name="Hippo">
<feeding-time>14:00</feeding-time>
</animal>
<animal name="Rattle Snake">
<feeding-time>9:00</feeding-time>
</animal>
<animal name="Flamingo">
<feeding-time>15:00</feeding-time>
</animal>
</zoo>
И моя страница XSL довольно пресная:
<xsl:template match="/">
<html>
<head>
<title>Real Estate Listings</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Я знаю, что мне нужно использовать пути локатора с использованием осей и / или группировки по Менчу — и я исследовал это в течение нескольких часов, и я все еще не имею ни малейшего представления о том, что происходит.
Я знаю, что мне нужно использовать функцию generate-id, и использовать функцию key — это хорошо, но опять же, я понятия не имею, как это реализовать — я потратил много часов в Google, пытаясь разобраться в этом материале.
Любая помощь была бы полезной.
Комментарии:
1. 1) Это домашнее задание? 2) Вы ограничены XSLT 1.0 или можете использовать 2.0?
2. Предполагая, что вы ограничены XSLT 1.0, я бы порекомендовал эту статью: jenitennison.com/xslt/grouping/muenchian.html Затем опубликуйте свою попытку внедрения XSLT … это даст людям больше оснований помогать вам.
3. Название вашего вопроса не соответствует деталям. Пожалуйста, будьте конкретны, вам нужна помощь с группировкой в XSLT или вы просто хотите создать привязочные ссылки? Также, как и просил Ларш, пожалуйста, подтвердите, ограничены ли вы XSLT 1.0 (будем надеяться, что нет)
4. Хороший вопрос, 1. Смотрите мой ответ для получения полного, короткого и простого решения. Также приводится объяснение.
Ответ №1:
Это преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kTimeByVal" match="feeding-time"
use="."/>
<xsl:key name="kAnimalByTime" match="@name"
use="../feeding-time"/>
<xsl:template match="/">
<xsl:apply-templates/>
<xsl:apply-templates mode="group"/>
</xsl:template>
<xsl:template match=
"feeding-time[generate-id()
=
generate-id(key('kTimeByVal',.)[1])
]
">
<a href="#{generate-id()}">
<xsl:value-of select="."/>
</a>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template mode="group" match=
"feeding-time[generate-id()
=
generate-id(key('kTimeByVal',.)[1])
]
">
<br /><p id="{generate-id()}"><xsl:text/>
<b><xsl:value-of select="."/> Feeding Time for:</b></p>
<xsl:apply-templates select="key('kAnimalByTime', .)"/>
</xsl:template>
<xsl:template match="@name">
<br /><xsl:value-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
<xsl:template mode="group" match="text()"/>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<zoo>
<animal name="Lion">
<feeding-time>11:00</feeding-time>
</animal>
<animal name="Penguin">
<feeding-time>14:00</feeding-time>
</animal>
<animal name="Elephant">
<feeding-time>9:00</feeding-time>
</animal>
<animal name="Tortoise">
<feeding-time>11:00</feeding-time>
</animal>
<animal name="Ape">
<feeding-time>16:00</feeding-time>
</animal>
<animal name="Hippo">
<feeding-time>14:00</feeding-time>
</animal>
<animal name="Rattle Snake">
<feeding-time>9:00</feeding-time>
</animal>
<animal name="Flamingo">
<feeding-time>15:00</feeding-time>
</animal>
</zoo>
выдает именно желаемый результат:
<a href="#d0e5">11:00</a>
<a href="#d0e11">14:00</a>
<a href="#d0e17">9:00</a>
<a href="#d0e29">16:00</a>
<a href="#d0e47">15:00</a>
<br/>
<p id="d0e5">
<b>11:00 Feeding Time for:</b>
</p>
<br/>Lion<br/>Tortoise<br/>
<p id="d0e11">
<b>14:00 Feeding Time for:</b>
</p>
<br/>Penguin<br/>Hippo<br/>
<p id="d0e17">
<b>9:00 Feeding Time for:</b>
</p>
<br/>Elephant<br/>Rattle Snake<br/>
<p id="d0e29">
<b>16:00 Feeding Time for:</b>
</p>
<br/>Ape<br/>
<p id="d0e47">
<b>15:00 Feeding Time for:</b>
</p>
<br/>Flamingo
И он отображается в браузере точно так, как требуется, и имеет желаемое поведение (щелчок по ссылке):
11:00
14:00
9:00
16:00
15:00
11:00 Время подачи для:
Лев
Черепаха
14:00 Время подачи для:
Пингвин
Бегемот
9:00 Время подачи для:
Слон
, змея-погремушка
16:00 Время подачи для:
Ape
15:00 Время подачи для:
Flamingo
Объяснение: Группировка по-мюнхенски, использование generate-id()
для генерации уникальных идентификаторов для использования в качестве привязок с использованием ключей.
Ответ №2:
Группировка в Мюнхене использует ключ, определенный на корневом уровне таблицы XSLT, который позволяет key
функции возвращать список всех элементов, которые соответствуют заданным критериям, а затем выбирает первый элемент из этого списка. Например:
<xsl:key name="feedingTime" match="*" use="feeding-time" />
Это позволяет вам вызывать key('feedingTime','11:00')
, чтобы получить список всех элементов, у которых есть feeding-time
элемент со значением 11:00
.
Вы можете использовать это в шаблоне с generate-id()
функцией, которая возвращает уникальное значение каждого идентификатора. Вы делаете это, сравнивая идентификатор элемента, который вы в данный момент обрабатываете, с идентификатором первого элемента в списке всех элементов с одинаковым feeding-time
значением. Вот так:
<xsl:if test="generate-id(feeding-time) = generate-id(key('feeding-time',feeding-time)[1])">
<!-- generate output -->
</xsl:if>
Или вы можете использовать то же условие в сопоставлении с шаблоном и использовать тот же ключ для перебора списка animal
узлов с текущим временем загрузки:
<xsl:template match="animal[generate-id() = generate-id(key('feedingTime',feeding-time)[1])]">
<!-- output a heading here, current node is first animal node with each feeding-time -->
<xsl:for-each select="key('feedingTime',feeding-time)">
<!-- output each animal here -->
</xsl:for-each>
</xsl:template>
Если вы это сделаете, вам нужно включить пустой шаблон, подобный этому: <xsl:template match="animal" />
для обработки оставшихся animal
элементов, отбрасывая их; вы уже имели дело с ними в for-each
цикле вышеупомянутого шаблона.
Вы можете использовать режимы шаблонов для обработки списка отдельно для ссылок и содержимого ниже, например:
<xsl:key name="feedingTime" match="*" use="feeding-time" />
<xsl:template match="zoo">
<xsl:apply-templates mode="links" />
<xsl:apply-templates mode="content" />
</xsl:template>
<xsl:template match="animal[generate-id() = generate-id(key('feedingTime',feeding-time)[1])]" mode="links">
<a href="#time_{feeding-time}">
<xsl:value-of select="feeding-time" />
</a>
</xsl:template>
<xsl:template match="animal[generate-id() = generate-id(key('feedingTime',feeding-time)[1])]" mode="content">
<p id="time_{feeding-time}">
<xsl:value-of select="concat(feeding-time,' Feeding time for:')" />
</p>
<ul>
<xsl:for-each select="key('feedingTime',feeding-time)">
<li>
<xsl:value-of select="@name" />
</li>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template match="animal" mode="links" />
<xsl:template match="animal" mode="content" />
Два шаблона внизу предназначены для обработки всех animal
элементов, которые не обрабатывались предыдущими (т. Е. 2-го и последующего animal
элемента для каждого времени подачи). Я не занимался форматированием здесь, но, надеюсь, это должно продемонстрировать методы, которые должны вам помочь.