2010-12-07 9 views
1

Мне нужно потянуть в элемент <sectionid/>, <amendmenttext/> и <sponsor/> элементов, если таковые имеются.получить последнюю группу предыдущих братьев с XSLT

Вот пример:

От:

<root> 
     <amendment> 
      <id>1</id> 
      <text>some text</text> 
     </amendment> 
     <sectionid>A</sectionid> 
     <sponsor>jon</sponsor> 
     <sponsor>peter</sponsor> 
     <amendment> 
      <id>8</id> 
      <text>some text</text> 
     </amendment> 
     <sectionid>B</sectionid> 
     <sponsor>matt</sponsor> 
     <sponsor>ben</sponsor> 
     <amendmenttext>some intro text</amendmenttext> 
     <amendment> 
      <id>5</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <id>4</id> 
      <text>some text</text> 
     </amendment> 
     <sponsor>max</sponsor> 
     <amendment> 
      <id>6</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <id>7</id> 
      <text>some text</text> 
     </amendment> 

</root> 

к:

<root> 
     <amendment>     
      <id>1</id> 
      <text>some text</text> 
     </amendment>   
     <amendment> 
      <sectionid>A</sectionid> 
      <sponsor>jon</sponsor> 
      <sponsor>peter</sponsor> 
      <id>8</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <sectionid>B</sectionid> 
      <sponsor>matt</sponsor> 
      <sponsor>ben</sponsor> 
      <amendmenttext>some intro</amendmenttext> 
      <id>5</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <sectionid>B</sectionid> 
      <sponsor>matt</sponsor> 
      <sponsor>ben</sponsor> 
      <id>4</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <sectionid>B</sectionid> 
      <sponsor>max</sponsor> 
      <id>6</id> 
      <text>some text</text> 
     </amendment> 
     <amendment> 
      <sectionid>B</sectionid> 
      <sponsor>max</sponsor> 
      <id>7</id> 
      <text>some text</text> 
     </amendment> 

</root> 

Примечание 1: <sectionid/> элемент относится ко всем <amendments/> до следующего <sectionid/>

Примечание 2: <sponsor/> применяется ко всем <amendments/> перед следующим списком <sponsor/>.

Примечание 3: Значения //amendment/id не являются последовательными.

Примечание 4: <amendment/> не может иметь <sponsor/> или <sectionid/> как предыдущий брат.

Примечание 5: <amendmenttext> относится только к следующему <amendment/>

Как это преобразование может быть сделано с помощью XSLT 1.0.

+0

Изменения в предыдущем вопросе http://stackoverflow.com/questions/4096481/refactor-xml-with-xsl является второстепенным. Я не думаю, что он заслуживает нового вопроса. – 2010-12-07 16:25:07

+0

Oki. Не зная, что решение будет похоже. Я думал, что это было несправедливо по отношению к первоначальным респондентам, чтобы изменить контекст вопроса после того, как они ответили. Но точка взята. – 2010-12-07 17:07:22

ответ

2

Эта таблица стилей (тот же ответ, чем раньше, но только одно правило):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="node()|@*"> 
     <xsl:param name="pSectionId" select="/.."/> 
     <xsl:param name="pSponsors" select="/.."/> 
     <xsl:variable name="vSectionid" select="self::sectionid"/> 
     <xsl:variable name="vSponsor" select="self::sponsor"/> 
     <xsl:variable name="vAmendment" select="self::amendment"/> 
     <xsl:if test="not($vSectionid|$vSponsor)"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:copy-of select="$pSectionId[$vAmendment]"/> 
       <xsl:copy-of select="$pSponsors[$vAmendment]"/> 
       <xsl:apply-templates select="node()[1]"/> 
      </xsl:copy> 
     </xsl:if> 
     <xsl:apply-templates select="following-sibling::node()[1]"> 
      <xsl:with-param name="pSectionId" 
          select="$pSectionId[not($vSectionid)]|$vSectionid"/> 
      <xsl:with-param name="pSponsors" 
          select="$pSponsors[not($vSponsor) or 
               current() 
                /preceding-sibling::node()[1] 
                /self::sponsor] | 
            $vSponsor"/> 
     </xsl:apply-templates> 
    </xsl:template> 
</xsl:stylesheet> 

Выход:

<root> 
    <amendment> 
     <id>1</id> 
     <text>some text</text> 
    </amendment> 
    <amendment> 
     <sectionid>A</sectionid> 
     <sponsor>jon</sponsor> 
     <sponsor>peter</sponsor> 
     <id>8</id> 
     <text>some text</text> 
    </amendment> 
    <amendment> 
     <sectionid>B</sectionid> 
     <sponsor>matt</sponsor> 
     <sponsor>ben</sponsor> 
     <id>5</id> 
     <text>some text</text> 
    </amendment> 
    <amendment> 
     <sectionid>B</sectionid> 
     <sponsor>matt</sponsor> 
     <sponsor>ben</sponsor> 
     <id>4</id> 
     <text>some text</text> 
    </amendment> 
    <amendment> 
     <sectionid>B</sectionid> 
     <sponsor>max</sponsor> 
     <id>6</id> 
     <text>some text</text> 
    </amendment> 
    <amendment> 
     <sectionid>B</sectionid> 
     <sponsor>max</sponsor> 
     <id>7</id> 
     <text>some text</text> 
    </amendment> 
</root> 

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

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