2014-11-04 5 views
0

Это, вероятно, сложный вопрос.Как выбрать узел и его братьев и сестер до тех пор, пока не произойдет тот же самый узел с начала

У меня есть этот документ:

<html> 
    <h1>title1</h1> 
    <p>content</p> 
    <ul> 
     <li>item</li> 
    </ul> 
    <h1>title2</h1> 
    <p>content</p> 
    <p>another content</p> 
    <h1>title3</h1> 
    <ol> 
     <li><p>text</p></li> 
    </ol> 
</html> 

Этот пример показывает, что у меня есть некоторые HTML, где «разделы» разделены на заголовки. Это заголовок, затем различное сочетание элементов, а затем заголовок снова.

Я хочу, чтобы эти участки должны быть обернуты div с использованием XSLT 2.

Итак, я хочу использовать <h1> заголовок для выбора групп. Основном правило группировка:

  • Выберите h1и все его братья и сестры, пока другой h1 не происходит.

Это напряжение на «и» очень важно, потому что я придумал XPath формул, выбранных узлов только между h1 узлов или выбрать из первого до последнего h1 игнорируя h1 между ними. Мне тоже нужно получить этот заголовок. Я не думаю, что это сложно сделать с XPath, но я не могу заставить его работать.

Для лучшего understandment, вот что он должен выглядеть следующим образом:

<html> 
    <div> 
     <h1>title1</h1> 
     <p>content</p> 
     <ul> 
     <li>item</li> 
     </ul> 
    </div> 
    <div> 
     <h1>title2</h1> 
     <p>content</p> 
     <p>another content</p> 
    </div> 
    <div> 
     <h1>title3</h1> 
     <ol> 
     <li><p>text</p></li> 
     </ol> 
    </div> 
</html> 

ответ

2

Вы можете использовать group-starting-with для этого:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="html"> 
    <xsl:copy> 
     <xsl:for-each-group select="node()" group-starting-with="h1"> 
     <div> 
      <xsl:copy-of select="current-group()" /> 
     </div> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

При запуске на образец, результат:

<html> 
    <div> 
     <h1>title1</h1> 
     <p>content</p> 
     <ul> 
     <li>item</li> 
     </ul> 
    </div> 
    <div> 
     <h1>title2</h1> 
     <p>content</p> 
     <p>another content</p> 
    </div> 
    <div> 
     <h1>title3</h1> 
     <ol> 
     <li> 
      <p>text</p> 
     </li> 
     </ol> 
    </div> 
</html> 

В качестве дополнительной информации, если вы хотите использовать group-by для этого, лет u мог сделать так вот так:

<xsl:for-each-group select="node()" group-by="self::h1 | preceding-sibling::h1[1]"> 

И это должно привести к такому же результату.

+0

Отлично! Я думал, что решение находится в XPath, но это было неправильно. XSLT предлагает такое элегантное, простое комплексное решение. Спасибо! – Allwe

+2

' 'должно быть сокращено до'

+0

@MartinHonnen Спасибо! Я редко использую XSLT 2.0 и не думал об этом. – JLRishe