первый последний элемент

XSLT XML Вопрос.

Заглядывая в простую трансформацию. У меня есть простой индекс XML ввода. Я должен вывести первый и последний элемент с для каждой главы. Как показано ниже. Любая помощь будет высоко ценится.

С уважением JJ

вход

<book>
  <page number="1">Chapter01</page> 
  <page number="2">Chapter01</page> 
  <page number="3">Chapter01</page> 
  <page number="4">Chapter01</page> 
  <page number="5">Chapter01</page> 
  <page number="6">Chapter01</page> 
  <page number="7">Chapter02</page> 
  <page number="8">Chapter02</page> 
  <page number="9">Chapter02</page> 
  <page number="10">Chapter02</page> 
  <page number="11">Chapter02</page> 
  <page number="12">Chapter02</page> 
  <page number="13">Chapter03</page> 
  <page number="14">Chapter03</page> 
  <page number="15">Chapter03</page> 
  <page number="16">Chapter03</page> 
  <page number="17">Chapter03</page> 
  <page number="18">Chapter03</page> 
 </book>

Выход

<book>
  <page number="1">Chapter01</page>  
  <page number="6">Chapter01</page> 
  <page number="7">Chapter02</page> 
  <page number="12">Chapter02</page> 
  <page number="13">Chapter03</page> 
  <page number="18">Chapter03</page> 
</book>

Ответы на вопрос(1)

Решение Вопроса

Обновлен, чтобы использовать преимущества более чистого предиката - благодаря @ SeanB.Durkin.

I. Решение XSLT 1.0

Когда это XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key name="kChapters" match="page" use="." />

  <xsl:template match="/*">
    <book>
      <xsl:apply-templates 
        select="page[generate-id() = generate-id(key('kChapters', .)[1])]" />
    </book>
  </xsl:template>

  <xsl:template match="page">
    <xsl:copy-of select=".|key('kChapters', .)[last()]" />
  </xsl:template>

</xsl:stylesheet>

... применяется к исходному XML:

<book>
  <page number="1">Chapter01</page>
  <page number="2">Chapter01</page>
  <page number="3">Chapter01</page>
  <page number="4">Chapter01</page>
  <page number="5">Chapter01</page>
  <page number="6">Chapter01</page>
  <page number="7">Chapter02</page>
  <page number="8">Chapter02</page>
  <page number="9">Chapter02</page>
  <page number="10">Chapter02</page>
  <page number="11">Chapter02</page>
  <page number="12">Chapter02</page>
  <page number="13">Chapter03</page>
  <page number="14">Chapter03</page>
  <page number="15">Chapter03</page>
  <page number="16">Chapter03</page>
  <page number="17">Chapter03</page>
  <page number="18">Chapter03</page>
</book>

... желаемый результат получается:

<?xml version="1.0"?>
<book>
  <page number="1">Chapter01</page>
  <page number="6">Chapter01</page>
  <page number="7">Chapter02</page>
  <page number="12">Chapter02</page>
  <page number="13">Chapter03</page>
  <page number="18">Chapter03</page>
</book>

Объяснение:

Обратите внимание на правильное использованиеMuenchian Grouping определить уникальный<page> элементы по их стоимости.Для каждого уникального<page> элемент, два<page> копируются элементы: первый и последний из группы, содержащей уникальное значение.

II. Решение XSLT 2.0

Обратите внимание, что в XSLT 2.0 решение становится еще проще.

Когда это XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="/*">
    <book>
      <xsl:for-each-group select="page" group-by=".">
        <xsl:copy-of select=".|current-group()[last()]" />
      </xsl:for-each-group>
    </book>
  </xsl:template>

</xsl:stylesheet>

... применяется к исходному XML, тот же желаемый результат получается:

<?xml version="1.0"?>
<book>
  <page number="1">Chapter01</page>
  <page number="6">Chapter01</page>
  <page number="7">Chapter02</page>
  <page number="12">Chapter02</page>
  <page number="13">Chapter03</page>
  <page number="18">Chapter03</page>
</book>

Объяснение:

Применяется та же методология, но вместо мюнхенской группировки XSLT 2.0for-each-group элемент иcurrent-group() инструкция используется.
 ABach29 окт. 2012 г., 03:57
Отличное предложение, @ SeanB.Durkin - спасибо.
 ABach29 окт. 2012 г., 04:08
@ SeanB.Durkin, мне было интересно об этом ... Я читал повсюду, но я не могу найти четкое объяснение разницы между<xsl:sequence> а также<xsl:copy-of>, Можете ли вы просветить меня?
 Sean B. Durkin29 окт. 2012 г., 03:57
Хорошее решение. В решении XSLT 1.0 вы можете еще больше рационализировать, комбинируя предикат для первого и последнего в один предикат, например[position()=1 or position()=last()].
 Sean B. Durkin29 окт. 2012 г., 04:35
Для узлов (не атомарных значений) copy-of создает копию, а последовательность просто делает ссылку. Обычно можно использовать последовательность для сбора ссылок на узлы в переменную, где имеет значение связь между собранными узлами и другими узлами.
 Sean B. Durkin29 окт. 2012 г., 04:06
Действительно подвесная точка в отношении решения XSLT 2.0: хотя в этой конкретной ситуации результат один и тот же, INMHO xsl: copy-of, вероятно, более семантически уместен, чем xsl: sequence.

Ваш ответ на вопрос