Выберите всех братьев и сестер между двумя узлами, исключая их

Я должен выбрать все содержимое между узлами h1.

<html>
<h1>Index</h1>
<p>some content</p>
<p>some more content</p>
<h1>Index 2</h1>
<p>some content</p>
<h2>other content</h2>
<h1>Index 3</h1>
<p>some  content</p>
<p>other content</p>
<h1>Index 4</h1>
<h2>some content</h2>
<p>other content</p>
</html>

Что должно привести к чему-то вроде этого:

<heading>
  <p>some content</p>
  <p>some more content</p>
<heading>
...

person Federico    schedule 10.02.2015    source источник


Ответы (2)


В XSLT 2.0 это хороший случай для group-starting-with:

<xsl:template match="html">
  <root>
    <xsl:for-each-group select="*" group-starting-with="h1">
      <heading text="{.}">
        <xsl:sequence select="current-group() except ."/>
      </heading>
    </xsl:for-each-group>
  </root>
</xsl:template>

current-group() — это вся группа элементов от одного h1 (включительно) до следующего (исключительно), а . — это первый узел в группе в порядке документа (h1), поэтому current-group() except . дает вам нужные узлы.

Вы можете предпочесть использовать select="node()" вместо select="*", если между элементами h1 может быть текст, который сам не заключен в другой элемент, например.

<h1>Example</h1>
Some unwrapped text
<p>...</p>
person Ian Roberts    schedule 10.02.2015

Это помогает.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:template match="/html">
      <xsl:apply-templates select="h1" />
    </xsl:template>

    <xsl:template match="h1">
      <heading>
        <xsl:copy-of select="following-sibling::*[preceding-sibling::h1[1] = current()][not(self::h1)]"/>
      </heading>
    </xsl:template>

</xsl:stylesheet>
person Federico    schedule 10.02.2015
comment
Обратите внимание, что предикат preceding-sibling::h1[1] = current() сравнивает значение этих двух узлов, а не их идентификаторы. Если бы у вас было два элемента h1, содержащих один и тот же текст, вы бы получили обе группы содержимого, отображаемые под одним и тем же heading. . Чтобы проверить один и тот же узел, а не одно и то же значение, вы должны использовать оператор is в XSLT 2.0 (preceding-sibling::h1[1] is current()) или сравнить их значения generate-id в 1.0 (generate-id(preceding-sibling::h1[1]) = generate-id(current())). - person Ian Roberts; 11.02.2015