开发者

get last group of previous-siblings with XSLT

I need to pull into an <amendment/> element the <sectionid/>, <amendmenttext/> and <sponsor/> elements if available.

Here is an example:

From :

<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>

to:

<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>

Note 1: the <sectionid/> element applies to all the <amendments/> before the next <sectionid/>

Note 2: the 开发者_Go百科<sponsor/> element applies to all the <amendments/> before the next <sponsor/> list.

Note 3: The values of //amendment/id are not sequential.

Note 4: An <amendment/> could not have a <sponsor/> or <sectionid/> as a previous-sibling.

Note 5: <amendmenttext> only applies to the following <amendment/>

How can this transformation be done with XSLT 1.0.


This stylesheet (the same answer than before but just one rule):

<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>

Output:

<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>

Note: The diference from previous answer is the default empty node set expression for parameters in those rules wich is needed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜