Как создавать ссылки-привязки с помощью XML и XSL?

#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 элемента для каждого времени подачи). Я не занимался форматированием здесь, но, надеюсь, это должно продемонстрировать методы, которые должны вам помочь.