Re: [xsl] finding closest node with certain characteristics

Subject: Re: [xsl] finding closest node with certain characteristics
From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 6 May 2014 15:26:43 -0000
Steve,

How about something like this? A brute force approach:

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

<xsl:template match="@break-after">
  <xsl:variable name="most-recent-psmi-wrapper"
    select="preceding::psmi:inserted-page-geometry[1]"/>
  <xsl:variable name="intervening" select="preceding::*[. >>
$most-recent-psmi-wrapper]"/>
  <xsl:if test="exists($intervening/@break-after |
$intervening[matches(.,'\S')])">
    <xsl:copy-of select="."/>
  </xsl:if>
</xsl:template>

I don't like it a whole lot ... it uses the preceding:: axis twice for
every @break-after. But it should work.

The logic could also be encapsulated as a function to make it more
easily reusable. Then you could simply match the offending nodes and
be done:

<xsl:template match="@break-after[f:just-wrapped(.)]"/>

(I'll leave the coding of the function, which should return
xs:boolean, to you. :-)

If the traversals on preceding:: bog you down, you could also consider
using a sibling traversal, but that involves extra overhead and is
probably harder for the maintenance programmer to deal with.

I hope this helps.

Cheers, Wendell

On Tue, May 6, 2014 at 10:24 AM, Steve Ylvisaker
ylvisaker.steve@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
wrote:
> forum:
>
> I am implementing a variation on Ken's PSMI process to accommodate some
> special needs for tax tables in our composition to PDF process. So, my input
> is a namespace fo file that contains a special wrapper:
> <psmi:inserted-page-geometry/>. This wrapper may occur multiple times within
> the XML instance.
>
> All is well with my psmi process, however, I can run into situations where
> an element following the psmi wrapper has the break-after="page" or
> break-before="page" attribute associated with it and is now redundant
> resulting in a blank page.
>
> So I need to find the first occurrence of any element with attribute
> break-after (or break-before) following a psmi wrapper and determine if
> there is any content between that element and the psmi wrapper. If there is
> no content then the page break request is likely redundant and needs to be
> defeated.
>
> Example data:
>
> <psmi:inserted-page-geometry>
>   <fo:table>
>    ~large table markup ~
>   </fo:table>
> </psmi:inserted-page-geometry>
> <fo:block margin-top="8pt">
>   <fo:marker marker-class-name="runningFoot"/>
>   <fo:block span="all" break-after="page"/>
>   <fo:block>Composition text here</fo:block>
>
> My problem is that the psmi wrapper may occur multiple times in the xml
> instance so I need to determine if my break-after element is the first one
> following the closest psmi wrapper. I know I have figured this out before
> but have a block trying to figure it out now.
>
> psudo code:
> <xsl:template match="*[@break-after]">
>  <xsl:choose>
> <!-- this test is where I need help, the rest I am fine with -->
>   <xsl:when test="(I am the first occurrence of an element with the
> attribute break-after following the closest psmi wrapper element) and
>                   (there is no content in the elements that exist between me
> and the closest psmi wrapper element)">copy the element without the
> break-after attribute</xsl:when>
>   <xsl:otherwise>copy the element as it occurred in the xml
> instance</xsl:otherwise>
>  </xsl:choose>>
> </xsl:template>
>
> Thanks for any clues.
> Steve
> 



-- 
Wendell Piez | http://www.wendellpiez.com
XML | XSLT | electronic publishing
Eat Your Vegetables
_____oo_________o_o___ooooo____ooooooo_^

Current Thread