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.
精彩评论