Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Динамическое группирование узлов XSLT посредством трансформации

Автор вопроса: scottОтветов: 3

Я пытаюсь создать подобную страницу с помощью XSLT-преобразования.

Страницы

  • Страница 1
  • страница 2

Ссылки

  • ссылка1
  • ссылка2

Вот xml

<siteMenu>
  <Pages>
    <title>page1</title>
  </Pages>
  <Pages>
    <title>page2</title>
  </Pages>
  <Links>
    <title>link1</title>
  </Links>
  <Links>
    <title>link2</title>
  </Links>
</siteMenu>

я пытался использовать

<xsl:for-each select="*"> and <xsl:for-each-group select="*" group-by="@v">

но это дает мне каждый элемент, но как я могу разделить их на основе родительского узла?

Я также хочу сделать его динамическим, чтобы, если я добавлю еще один элемент в siteMenu, он соответствующим образом обновил xslt.

foreachxslttransform

Ответы

Ответ 1 · рейтинг 4 · Tomalak

Итак, вы хотите сгруппировать по имени узла. Не лучшая идея хранить в узлах XML больше, чем фактическую информацию о структуре, но вот так:

<siteMenu>
  <Pages>
    <title>page1</title>
  </Pages>
  <Pages>
    <title>page2</title>
  </Pages>
  <Links>
    <title>link1</title>
  </Links>
  <Links>
    <title>link2</title>
  </Links>
  <Sites>
    <title>site1</title>
  </Sites>
  <Sites>
    <title>site2</title>
  </Sites>
</siteMenu>

и это преобразование XSLT 2.0 (только соответствующий фрагмент):

<xsl:template match="siteMenu">
  <xsl:for-each-group select="*" group-by="name()">
    <xsl:sort select="name()" />
    <div>
      <h1><xsl:value-of-select="current-grouping-key()" /></h1>
      <ul>
        <xsl:for-each select="current-group()">
          <li><xsl:value-of select="title" /></li>
        </xsl:for-each>
      </ul>
    </div>
  </xsl:for-each-group>
</xsl:template>

или это преобразование XSLT 1.0 (только соответствующий фрагмент):

<xsl:key name="kMenu" match="siteMenu/*" use="name()" />

<xsl:template match="siteMenu">
  <xsl:for-each select="*[
    generate-id() = generate-id(key('kMenu', name())[1])
  ]">
    <xsl:sort select="name()" />
    <div>
      <h1><xsl:value-of-select="name()" /></h1>
      <ul>
        <xsl:for-each select="key('kMenu', name())">
          <li><xsl:value-of select="title" /></li>
        </xsl:for-each>
      </ul>
    </div>
  </xsl:for-each-group>
</xsl:template>

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

<siteMenu>
  <section name="Pages">
    <title>page1</title>
    <title>page2</title>
  </section>
  <section name="Links">
    <title>link1</title>
    <title>link2</title>
  </section>
  <section name="Sites">
    <title>site1</title>
    <title>site2</title>
  </section>
</siteMenu>

Ответ 2 · рейтинг 1 · Oded

Вы selecting все (*).

Используйте select="Pages" для выбора страниц и select="Links" для ссылок.

Узнайте о выражениях XPath здесь.

Ответ 3 · рейтинг 1 · ndim

я бы начал с

<ul>
  <xsl:for-each select="//Pages">
    <li><xsl:value-of select="./title"/></li>
  </xsl:for-each>
</ul>

и продолжить оттуда.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы