xsl-list
[Top] [All Lists]

Re: [xsl] finding closest node with certain characteristics

2014-05-06 10:26:55
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(_dot_)steve(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com>
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_^
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>