2013-05-14 4 views
1

Я использую xslt 2.0, у меня есть следующий образец xml, я хочу получить все узлы «header-lightgray» между двумя «заголовками-серыми» узлами, проблема здесь: «Не знаю, сколько« заголовок-лайтгейв »есть. поэтому я не могу использовать функцию position(). и xsl для каждого не поддерживают разрыв.Как получить узлы в этом случае

<t> 
<parent class="header-gray"></parent> 
<parent class="header-lightgray"></parent> 
<parent class="header-lightgray"></parent> 
<parent class="header-lightgray"></parent> 
... 
<parent class="header-gray"></parent> 
<parent class="header-lightgray"></parent> 
<parent class="header-lightgray"></parent> 
<parent class="header-lightgray"></parent> 
<parent class="header-gray"></parent> 
</t> 

Я хочу пройти через них и заменить все узлы, заголовок-серый с div и header-lightgray с диапазоном. ожидаемый выход:

<div class="header-gray"> 
<span class="header-lightgray"/> 
<span class="header-lightgray"/> 
<span class="header-lightgray"/> 
... 
</div> 
<div class="header-gray"> 
<span class="header-lightgray"/> 
<span class="header-lightgray"/> 
<span class="header-lightgray"/> 
</div> 

Как это сделать?

Любая помощь приветствуется.

Решение Я хотел бы поделиться в соответствии с ответом Яна Vlcinsky в:

<xsl:for-each select="/t/parent[@class='header-gray']"> 
    <xsl:variable name="ns1" select="current()/following-sibling::parent"/> 
    <xsl:variable name="ns2" select="current()/following-sibling::parent[@class='header-gray'][1]/preceding-sibling::parent"/> 
    <div class="header-gray"> 
    <xsl:for-each select="$ns1[count(.| $ns2)=count($ns2)]"> 
    <span class="header-lightgray"/>  
    </xsl:for-each> 
    </div> 
</xsl:for-each> 

Я не проверить выше кода, но это та же самая логика в моем реальном коде. Я не использовал xslt 2.0, потому что нашел, что lxml 2.3, который я использую, не поддерживает xslt 2.

+0

Что вы хотите делать с этими элементами после их появления? Какую версию XSLT вы используете? – Borodin

+0

Я хочу пройти через них и заменить все узлы, заголовок-серый с div и header-lightgray с диапазоном. span находится в div. –

ответ

0

Посмотрите раздел «3. Позиционные задачи группировка» в нижней части страницы http://gandhimukul.tripod.com/xslt/grouping20.html

Ваш вопрос, кажется, своего рода дубликат: How would you find all nodes between two H3's using XPATH?

Вопрос XPath : select all following siblings until another sibling сделки с тем же тоже.

+0

Спасибо! Метод Kayessian для пересечения множества узлов действительно потрясающий, он решил мою проблему. –

-1

Вот один из способов сделать это.

Когда это XSLT 2.0 решение:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/*"> 
     <t> 
     <xsl:apply-templates 
      select="parent[@class = 'header-gray'][following-sibling::*]"/> 
     </t> 
    </xsl:template> 

    <xsl:template match="*[@class = 'header-gray']"> 
     <div class="{@class}"> 
     <xsl:apply-templates 
      select=" 
      following-sibling::*[@class = 'header-lightgray'] 
       intersect 
      following-sibling::*[@class = 'header-gray'][1]/ 
       preceding-sibling::*[@class = 'header-lightgray']"/> 
     </div> 
    </xsl:template> 

    <xsl:template match="*[@class = 'header-lightgray']"> 
     <span class="{@class}"/> 
    </xsl:template> 

</xsl:stylesheet> 

... применяется к предоставленному XML (завернутый в элемент верхнего уровня, чтобы сделать документ хорошо сформированную):

<t> 
    <parent class="header-gray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-gray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-lightgray"/> 
    <parent class="header-gray"/> 
</t> 

... желаемый результат получается:

<t> 
    <div class="header-gray"> 
    <span class="header-lightgray" /> 
    <span class="header-lightgray" /> 
    <span class="header-lightgray" /> 
    </div> 
    <div class="header-gray"> 
    <span class="header-lightgray" /> 
    <span class="header-lightgray" /> 
    <span class="header-lightgray" /> 
    </div> 
</t> 

В этом решении используется XPath 2.0's intersect operation.

+1

Даун-голоса без объяснений не помогают, ребята. – ABach

+0

Боюсь, вам нужно научиться принимать поданные голоса. Подавляющее большинство избирателей не оставляют никаких объяснений, и я считаю, что это лучше всего. Мое мнение о ваших ответах заключается в том, что вы слишком заинтересованы, чтобы соответствовать требуемому результату, не задумываясь о намерениях OP или о лучшем методе. Кажется, вы используете Stack Overflow в качестве источника упражнений. Если это так, то вы должны помнить, что нет никаких оснований публиковать ваши усилия, если вы не считаете их образцовыми. И * пожалуйста * пересмотреть свое злоупотребление ** жирным ** в ваших ответах. Это не стиль, который нужно скопировать. – Borodin

0

Это преобразование:

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

<xsl:template match="/*"> 
    <t> 
    <xsl:for-each-group select="*" 
     group-starting-with="parent[@class='header-gray']"> 
    <div class="header-gray"> 
     <xsl:apply-templates select="current-group()[position() ne 1]"/> 
    </div> 
    </xsl:for-each-group> 
    </t> 
</xsl:template> 

<xsl:template match="parent"> 
    <span class="{@class}"/> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на следующий документе XML (предоставленный фрагмент, завернутый в один верхний элемент так, что он становится хорошо сформированным XML-документ):

<t> 
    <parent class="header-gray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-gray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-lightgray"></parent> 
    <parent class="header-gray"></parent> 
</t> 

производит разыскиваемого, правильный результат:

<t> 
    <div class="header-gray"> 
     <span class="header-lightgray"/> 
     <span class="header-lightgray"/> 
     <span class="header-lightgray"/> 
    </div> 
    <div class="header-gray"> 
     <span class="header-lightgray"/> 
     <span class="header-lightgray"/> 
     <span class="header-lightgray"/> 
    </div> 
    <div class="header-gray"/> 
</t>