XSLT Группировка - PullRequest
       10

XSLT Группировка

5 голосов
/ 03 февраля 2009

У меня есть простой XML с двумя уровнями (заголовок и строка) тегов, таких как:

<?xml version="1.0"?>
<Header>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
</Header>

Мне нужно сгруппировать строки по наборам из X (например, X = 3) строк, чтобы мой вывод был следующим:

<?xml version="1.0"?>
<Header>
    <set>
        <line>Line 1</line>
        <line>Line 2</line>
        <line>Line 3</line>
    </set>
    <set>
        <line>Line 4</line>
        <line>Line 5</line>
        <line>Line 6</line>
    </set>
    <set>
        <line>Line 7</line>
        <line>Line 8</line>
        <line>Line 9</line>
    </set>
</Header> 

Как мне написать XSLT, который может выполнять такие преобразования?

Спасибо!

O

Ответы [ 4 ]

4 голосов
/ 03 февраля 2009

Следующее преобразование дает требуемый результат :

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vN" select="3"/>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates 
           select="line[position() mod $vN = 1]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="line">
    <set>
      <xsl:apply-templates mode="copy" select= 
       ". 
       | 
        following-sibling::line[position() &lt; $vN]"/>
    </set>
  </xsl:template>

    <xsl:template match="line" mode="copy">
      <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

При применении к предоставленному документу XML :

<Header>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
</Header>

результат :

<Header>
  <set>
    <line>Line 1</line>
    <line>Line 2</line>
    <line>Line 3</line>
  </set>
  <set>
    <line>Line 4</line>
    <line>Line 5</line>
    <line>Line 6</line>
  </set>
  <set>
    <line>Line 7</line>
    <line>Line 8</line>
    <line>Line 9</line>
  </set>
</Header>

Обратите внимание на следующее :

  1. Использование оператора XPath mod для определения первого элемента line в каждой группе vN элементов.

  2. Использование режимов , чтобы можно было обрабатывать различные line элементы по разным шаблонам

1 голос
/ 03 февраля 2009

http://www.xml.com/pub/a/2003/11/05/tr.html показывает немного менее уродливый способ сделать это с помощью XSLT 2.0. Ключевой элемент это:

<xsl:for-each-group select="*" group-ending-with="*[position() mod 3 = 0]">

1 голос
/ 03 февраля 2009

Как правило, в XSLT, если вы хотите создать иерархию из списка, вы можете использовать ключевые слова previous-sibling и follow-sibling. Это проще, если между наборами есть запись маркера.

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

Я не пробовал, но это был бы мой первый старт.

xslt - это, как правило, хорошее место для понимания различных ключевых слов.

0 голосов
/ 03 февраля 2009

Это должно быть возможно. Имеет желаемый выход:

<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

  <xsl:template match="/Header">
    <Header>
      <xsl:for-each select="line">
        <xsl:if test="not(number()=0) and position() mod 3 = 0">
          <set>
            <xsl:variable name="pos" select="position()"/>
            <line><xsl:value-of select="../line[position()=($pos -2)]"/></line>
            <line><xsl:value-of select="../line[position()=($pos -1)]"/></line>
            <line><xsl:value-of select="text()"/></line>
            </set>
        </xsl:if>

      </xsl:for-each>
    </Header>
  </xsl:template>

</xsl:stylesheet>

(штука $ pos-1, $ pos-2 не очень красивая)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...