Re: [xsl] Creating a container element for siblings which have different start and end elements

Subject: Re: [xsl] Creating a container element for siblings which have different start and end elements
From: "Wendell Piez wapiez@xxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 30 Jan 2015 19:51:12 -0000
Michael,

There are a number of ways of cracking this particularly tough nut.

For simpler cases, you can get away with working somewhat as you are
doing so, except using keys or functions for your logic instead of
bare-bones XPath. That way you can get a little more leverage for
splitting and splicing.

So here is an approach that might work for you. Note that it assumes
that: (a) your starts and ends are properly paired, and (b) they are
always siblings. It uses a pair of keys to point back and forth
between tech:revst elements and their "contents", i.e. the sibling
nodes to which they apply. Since internally generated identifiers make
a convenient way to key to individual nodes, we use them.

If starts and ends are not always siblings, this method isn't strong
enough, but here goes:

  <xsl:key name="revised-by-starter"
match="node()[not(preceding-sibling::tech:revend[1] >>
preceding-sibling::tech:revst[1])]"
    use="preceding-sibling::tech:revst[1]/generate-id(.)"/>

  <xsl:key name="starter-by-revised-ids" match="tech:revst"
    use="(following-sibling::node() except
following-sibling::tech:revend[1]/following-sibling::node())/generate-id(.)"/
>


  <!-- We alias the default mode as 'copy' so we can get back into it. -->
  <xsl:template match="node() | @*" mode="#default copy">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <!-- template matches any node whose generated ID returns a
tech:revst, using the key, and suppresses it from output -->
  <xsl:template
match="node()[exists(key('starter-by-revised-ids',generate-id(.)))]"/>

  <xsl:template match="tech:revst">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates
select="key('revised-by-starter',generate-id(.))" mode="copy"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

This is only very lightly tested, and there could also be paste errors --

I hope that helps, Wendell


On Thu, Jan 29, 2015 at 11:25 AM, Michael Friedman
sumarimike@xxxxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
wrote:
> Greetings,
>
> I have some XML which has certain elements Ibd like to move into a
containing element. Ibm having trouble.
>
> The current XML is arranged this way:
> <para>Planes have wings so they can <tech:revst
type="Airline"/>fly<tech:revend/> in the sky and get us to places webd like
to visit faster <tech:revst type="Airline"/>than if webd walked
there.<caution>
> <para>Please stay in the airplane at all
times</para></caution><tech:revend/></para>
>
> In this older method of indicating a revision markup area, <tech:revst/> is
used to indicate a start of a change and <tech:revend> is used to indicate the
end. There can be multiple instances of this revision markup anywhere,
surrounding text within elements, or surrounding multiple elements and text.
These containers produce change bars in PDF and background-color areas in
HTML.
>
> I am producing PDF and HTML output. In order to create a <span> or <div> in
HTML output, Ibd like to pre-process the XML to produce the following
desired XML output structure.
>
> Desired output:
> <para>Planes have wings so they can <tech:revst
type="Airline">fly</tech:revst><tech:revend/> in the sky and get us to places
webd like to visit faster <tech:revst type="Airline">than if webd walked
there.<caution>
> <para>Please stay in the airplane at all
times</para></caution></tech:revst><tech:revend/></para>
>
> Essentially, Ibd like to encapsulate the siblings between the
<tech:revst/> and <tech:revend/> into the <tech:revst>. The <tech:revend/> is
left in for FO processing.
>
> Using XSLT 2.0, Ibve been able to get the first <tech:revst> in a given
sibling structure partially handled. However, the remaining ones (in this
case) are omitted. Ibm using saxon 6 via our publishing app to do the heavy
lifting.
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>                         xmlns:tech="http://www.techpubsglobal.com/";
>                         version="2.0">
>
>     <xsl:output method="xml" indent="no" doctype-public="-//Tech//DTD
FlightBook XML V4.0//EN" doctype-system="flightbook.dtd"/>
>
>     <xsl:template match="/|*|comment()|processing-instruction()">
>        <xsl:call-template name="do_copy"/>
>     </xsl:template>
>
>     <xsl:template match="tech:revst">
>             <xsl:element name="tech:revst">
>                   <xsl:for-each select="@*">
>                         <xsl:attribute name="{name(.)}">
>                   <xsl:value-of select="."/>
>                 </xsl:attribute>
>             </xsl:for-each>
>                   <xsl:for-each
select="following-sibling::*[not(self::tech:revend)][not(preceding-sibling::t
ech:revend)]|following-sibling::text()[preceding-sibling::tech:revst][followi
ng-sibling::tech:revend]">
>                         <xsl:copy>
>                         <xsl:for-each select="@*">
>                                     <xsl:copy/>
>                               </xsl:for-each>
>                               <xsl:apply-templates/>
>                     </xsl:copy>
>                   </xsl:for-each>
>             </xsl:element>
>       </xsl:template>
>
>       <xsl:template
match="*[preceding-sibling::tech:revst][following-sibling::tech:revend]"/>
>       <xsl:template
match="text()[preceding-sibling::tech:revst][following-sibling::tech:revend]"
/>
>
>       <xsl:template name="do_copy">
>           <xsl:copy>
>             <xsl:for-each select="@*">
>                         <xsl:copy/>
>                   </xsl:for-each>
>                   <xsl:apply-templates/>
>         </xsl:copy>
>     </xsl:template>
>
> </xsl:stylesheet>
>
> The following is produced from this stylesheet:
> <para>Planes have wings so they can <tech:revst type="Airline">fly in the
sky and get us to places webd like to visit faster than if webd walked
there.</tech:revst><tech:revend/></para>
>
> I found some useful suggestions on grouping on the dpawson.co.uk site, but
each one I tried didnbt quite get me what I was looking for. In particular,
there was a bWorking with pairs of siblingsb that used sequences, but I
still couldnbt get that to work when there were multiple
<tech:revst/><tech:revend/> pairs in a set of siblings.
>
> Suggestions?
>
> Thanks,
> Michael Friedman
>



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

Current Thread