2016-06-11 17 views
0

Я хочу разбить XML-документ (фактически, XHTML) в разделах по тегам верхнего уровня h1. Все, начиная с первого из <h1> до следующего, должно быть обернуто в элемент <section> и так далее, до конца документа.Оберните все между двумя вхождениями тегов с XSLT 1.0

Например, если у меня есть этот исходный документ:

<article> 
    <h1>Heading 1</h1> 
    <p>Some text</p> 
    <p>Some more text</p> 

    <h1>Heading 2</h1> 
    <p>Some text</p> 
    <h2>Subheading</h2> 
    <p>Some text</p> 

    <h1 id="heading3">Heading 3</h1> 
    <p>Some text</p> 
</article> 

Я хочу, чтобы результат точно так:

<article> 
    <section> 
     <h1>Heading 1</h1> 
     <p>Some text</p> 
     <p>Some more text</p> 
    </section> 
    <section> 
     <h1>Heading 2</h1> 
     <p>Some text</p> 
     <h2>Subheading</h2> 
     <p>Some text</p> 
    </section> 
    <section> 
     <h1 id="heading3">Heading 3</h1> 
     <p>Some text</p> 
    </section> 
</article> 

Проблема в том, все у меня есть libxslt1.1 (таким образом, , XSLT 1.0 + EXSLT). С XSLT 2.0 я мог бы что-то сделать с красивым <xsl:for-each-group select="*" group-starting-with="h1">, но, к сожалению, это не жизнеспособный вариант для меня.

Я не хочу группировать значения атрибутов (у меня нет каких-либо значимых атрибутов), поэтому, насколько я понимаю, группировка Muenchian - это не трюк, который бы сработал для меня. Может быть, я ошибаюсь, хотя я только что прочитал об этом методе несколько минут назад.

Есть ли способ достичь этого с помощью XSLT 1.0?

ответ

2

как я понимаю, группировка Muenchian - это не трюк, который бы работал для меня .

Ну, что-то очень близко к этому будет:

XSLT 1,0

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

<xsl:key name="grpById" match="*[not(self::h1)]" use="generate-id(preceding-sibling::h1[1])" /> 

<xsl:template match="/article"> 
    <xsl:copy> 
     <xsl:for-each select="h1"> 
      <section> 
       <xsl:copy-of select=". | key('grpById', generate-id())"/> 
      </section> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

Спасибо, он работает безупречно! Я не знал о 'generate-id (previous-sibling :: h1 [1])'. Всегда хорошо учиться чему-то новому. – drdaeman

2

Используйте ключ name="group" match="article/*[not(self::h1)]" use="count(preceding-sibling::h1)", то в шаблоне сопоставления article применять шаблоны для h1 дочерних элементов и шаблон для h1 создать раздел и скопировать .|key('group', position()).