2015-02-18 10 views
3

Учитывая следующий XMLрасщепленные дочерние элементы в подразделах

<section> 
    <title>Title1</title> 
    <item>Item1</item> 
    <item>Item2</item> 
    <title>Title2</title> 
    <item>Item1</item> 
    <item>Item2</item> 
</section> 

Что это самый простой способ разделить на второй титул в этом

<section> 
    <subsection> 
     <title>Title1</title> 
     <item>Item1</item> 
     <item>Item2</item> 
    </subsection> 
    <subsection> 
     <title>Title2</title> 
     <item>Item1</item> 
     <item>Item2</item> 
    </subsection> 
</section> 

, например, следующий шаблон был один идея, но XPath кажется сложным.

<xsl:template match="section"> 
    <xsl:copy> 
     <subsection> 
       <xsl:apply-templates select="...those before second title..."/> 
     </subsection> 
     <subsection> 
       <xsl:apply-templates select="...those including and after second title..."/> 
     </subsection> 
    </xsl:copy> 
</xsl:template> 

ответ

3

С XSLT 2.0 или более поздней версии, это просто использование for-each-group:

<xsl:template match="section"> 
    <xsl:copy> 
     <xsl:for-each-group select="*" group-starting-with="title"> 
      <subsection> 
        <xsl:apply-templates select="current-group()"/> 
      </subsection> 
     </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

В 1.0 вы можете достичь аналогичного эффекта с такой логикой:

<xsl:template match="section"> 
    <xsl:copy> 
     <xsl:for-each select="title"> 
      <subsection> 
        <xsl:apply-templates select=". | following-sibling::item[ 
            generate-id(preceding-sibling::title[1]) 
           = generate-id(current())]"/> 
      </subsection> 
     </xsl:for-each> 
    </xsl:copy> 
</xsl:template> 

Предикат находит те, которые следуют за родным братом: item Элементы текущего title, ближайший предшествующий title - это тот, с которого мы начали.

Одно различие между этими двумя подходами, если у вас есть какие-либо другие элементы в section перед первойtitle, то for-each-group подход поставит их в ведущей части (которая не будет иметь никакого названия), в то время как 1,0 подход будет игнорировать их.


Если вы хотите всегда ровно два подразделов (со всем после второго title во второй части, в том числе любых дополнительных title элементов), то вы можете просто жестко закодировать его как

<xsl:template match="section"> 
    <xsl:copy> 
     <subsection> 
       <xsl:apply-templates select="title[2]/preceding-sibling::*"/> 
     </subsection> 
     <subsection> 
       <xsl:apply-templates select="title[2] | title[2]/following-sibling::*"/> 
     </subsection> 
    </xsl:copy> 
</xsl:template> 

(Обратите внимание, что если элементов меньше title, это приведет к двум полностью пустым элементам <subsection/>)

Смежные вопросы