2013-05-24 2 views
0

Привет У меня есть документ XML, который выглядеть:Wrap упорядоченный список узлов

<a> <!-- Several nodes "a" with the same structure for children --> 
    <b>12</b> 
    <c>12</c> 
    <d>12</d> 
    <e>12</e> 
    <f>12</f> 
    <g>12</g> 
</a> 

Я пытаюсь получить следующий документ с помощью XSLT 2,0

<a> 
    <b>12</b> 
    <c>12</c> 
    <wrap> 
     <d>12</d>   
     <e>12</e> 
     <f>12</f> 
     <g>12</g> 
    </wrap> 
</a> 

Я начал свою XSL файл с

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

И изменили его несколько случаев, как заменить часть строки, фильтровать некоторые узлы и т.д. Но я застрял в «выборе четырех последовательных узлов», какой-нибудь подсказке о том, как добиться обертывания?

+0

Вы можете выбрать узлы, чтобы обернуть, в частности? Всегда ли это одно и то же множество (d, e, f, g)? –

+0

Это всегда одно и то же множество с тем же порядком (d, e, f, g) –

ответ

1

С XSLT 2.0 вы также можете использовать for-each-group group-adjacent:

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

    <xsl:output indent="yes"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="a"> 
     <xsl:copy> 
     <xsl:for-each-group select="*" group-adjacent="boolean(self::d | self::e | self::f | self::g)"> 
      <xsl:choose> 
      <xsl:when test="current-grouping-key()"> 
       <wrap> 
       <xsl:apply-templates select="current-group()"/> 
       </wrap> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:apply-templates select="current-group()"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 

    </xsl:stylesheet> 
+0

Работает как шарм, спасибо! –

2

Если все ваши a элементы действительно точно такую ​​же структуру, то самое простое было бы перебором

<xsl:template match="a"> 
    <xsl:copy> 
    <xsl:apply-templates select="b | c" /> 
    <wrap> 
     <xsl:apply-templates select="d | e | f | g" /> 
    </wrap> 
    </xsl:copy> 
</xsl:template> 

или если вы хотите быть немного поумнее

<wrap> 
     <xsl:apply-templates select="* except (b | c)" /> 
    </wrap> 

Если вы хотите всегда «обертывать» последние четыре дочерних элемента a, то как насчет

<xsl:template match="a"> 
    <xsl:variable name="lastFour" select="*[position() &gt; (last() - 4)]" /> 
    <xsl:copy> 
    <xsl:apply-templates select="* except $lastFour" /> 
    <wrap> 
     <xsl:apply-templates select="$lastFour" /> 
    </wrap> 
    </xsl:copy> 
</xsl:template> 
+0

Правильный ответ тоже, спасибо! –

+0

плюс один для простоты - ошибка, специфика –

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