Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: [xsl] targeting the last element in a node or consecutive elements

From: Chuck Bearden <cbearden@-------->
To:
Date: 1/4/2007 10:14:00 PM
Your second 'apply-templates' rule will omit text and comment nodes, 
but that may not be important to your use case.

I adapted Jarno Elovirta's tree walking design pattern [1] for your
problem.  It's rather verbose and probably overkill for your 
problem, but you can see that this pattern of node-by-node walking
is quite powerful and can be adapted to many uses.

[1] http://www.dpawson.co.uk/xsl/sect2/N4486.html#d5280e1102

--------------------------------------------------------------------
<?xml version="1.0"?>

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:output indent="yes" method="xml"/>

  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="somenode">
    <xsl:param name="nodeType">start</xsl:param>
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <!-- Step into 'walk' mode and process first child node -->
      <xsl:apply-templates select="node()[1]" mode="walk">
        <xsl:with-param name="nodeType" select="$nodeType"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

<!-- 'walk' mode templates -->

  <!-- 'walk' mode; PI with no elements in following-sibling axis -->
  <xsl:template match="processing-instruction()
      [not(following-sibling::*)]" mode="walk">
    <xsl:param name="nodeType"/>
    <xsl:if test="$nodeType='elem'">
    <!-- We are in the first PI after the last element; 
         do any special processing here -->
      <insertedElement/><xsl:text>
</xsl:text>
    </xsl:if>
    <!-- Apply default mode templates to this node -->
    <xsl:apply-templates select="."/>
    <!-- Walk on to next sibling node -->
    <xsl:apply-templates select="following-sibling::node()[1]" mode="walk">
      <xsl:with-param name="nodeType">pi</xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

  <!-- 'walk' mode; all other nodes -->
  <xsl:template match="node()" mode="walk">
    <xsl:param name="nodeType"/>
    <!-- Apply default mode templates to this node -->
    <xsl:apply-templates select="."/>
    <!-- Walk on to next sibling node -->
    <xsl:apply-templates select="following-sibling::node()[1]" mode="walk">
    <!-- Tell following templates which of element or pi was last seen -->
      <xsl:with-param name="nodeType">
        <xsl:choose>
          <xsl:when test="self::*">elem</xsl:when>
          <xsl:when test="self::processing-instruction()">pi</xsl:when>
          <xsl:otherwise><xsl:value-of select="$nodeType"/></xsl:otherwise>
        </xsl:choose>
      </xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

<!-- Default mode templates; standard identity transforms -->
  <xsl:template match="*">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*|text()|comment()">
    <xsl:copy/>
  </xsl:template>

  <xsl:template match="processing-instruction()">
  <!-- Special treatment for PIs? -->
    <xsl:copy/>
  </xsl:template>

</xsl:stylesheet>
--------------------------------------------------------------------

Chuck
--
Chuck Bearden ---------------------------------- C o n n e x i o n s
Sr. Content Specialist                        Rice University MS 375
cbearden@xxxxxxxx                                        PO Box 1892
AIM: Schleifheim                              Houston, TX 77251-1892
713.348.3661 (voice) --- <http://cnx.org/> ------ (fax) 713.348.3665

> From: egarrett@xxxxxxxxxxxx <egarrett@xxxxxxxxxxxx>
> Date: Jan 4, 2007 2:42 PM
> Subject: Re: [xsl] targeting the last element in a node or consecutive 
> elements
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> 
> 
> This appears to be working:
> 
>               <xsl:apply-templates select="node()[not(self::processing-
> instruction()[not(following-sibling::*)])]"/>
> 
> Then I insert the extra element.  Then grab the PIs I suppressed above:
>               <xsl:apply-templates select="node()[self::processing-
> instruction()[not(following-sibling::*)]]"/>
> 
> Does it look right?
> 
> Thanks.
> --emily
> 
> ----- Original Message -----
> From: <egarrett@xxxxxxxxxxxx>
> Date: Thursday, January 4, 2007 2:21 pm
> Subject: Re: [xsl] targeting the last element in a node or consecutive
> elements
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> 
> >Here is my logic so far to target everything in the node, and if
> >it is
> >a processing-instruction it should be processed only if something
> >exists after it other than another processing-instruction.  What I
> >have
> >below does not work because I think it is looking for the second
> >processing-instruction inside the first one rather than following
> >it,
> >but it is starting to feel like it is possible to put what I need
> >in
> >one instruction.
> >
> ><xsl:apply-templates select="node()[not(self::processing-instruction()
> >[not(following::*[not(self::processing-instruction())])])]"/>
> >
> >Warning: on line 58 of file:/C:/Documents%20and%
> >20Settings/egarrett/Desktop/Transforms%20R%20Us/saxon/xsl/X3B.xsl:
> > The self axis will never select any element() nodes when
> >starting at
> >an
> > processing-instruction() node
> >
> >Any ideas?
> >----- Original Message -----
> >From: egarrett@xxxxxxxxxxxx
> >Date: Thursday, January 4, 2007 9:59 am
> >Subject: Re: [xsl] targeting the last element in a node or
> >consecutive
> >elements
> >To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> >
> >> Yes, your example is correct.  I don't know if or how many PIs
> >> will
> >> occur at the end of the node.
> >>
> >> P.S. I started a new post because they changed the
> >> requirements....
> >>
> >> ----- Original Message -----
> >> From: Abel Braaksma <abel.online@xxxxxxxxx>
> >> Date: Thursday, January 4, 2007 9:53 am
> >> Subject: Re: [xsl] targeting the last element in a node or
> >> consecutive
> >> elements
> >> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> >>
> >> > Hi Emily,
> >> >
> >> > This is a double post, you already opened this discussion
> >under
> >> > "suppressing only the last PI" (which differed in details,
> >however).> >
> >> > If I may, it appears that you want to do this:
> >> >
> >> > <somenode>
> >> >    <node1 />
> >> >    <?instr1?>
> >> >    <node2 />
> >> >    <?instr2?>
> >> >    <?instr3?>
> >> > </somenode>
> >> >
> >> > 1. Process node1, instr1, node2 etc
> >> > 2. Do something before instr2 and instr3 (being consecutively
> >> and
> >> > together at the end of a node)
> >> > 3. Process instr2 and instr3
> >> > (if instr2 and instr3 were not there, you want to skip
> >> processing
> >> > step 2
> >> > and 3?)
> >> >
> >> > Am i right? Please confirm (and/or give your sample input, to
> >> make
> >> > the
> >> > subject easier)
> >> >
> >> > Cheers,
> >> > -- Abel
> >> >
> >> > Emily.Garrett@xxxxxxxxxxx wrote:
> >> > > I'm trying to use xsl:apply templates to grab the entire
> >> content
> >> > of a
> >> > > node, except for any PIs that may be at the very end of the
> >> > node.  I can
> >> > > see how position()=last() can be used to refer to the very
> >> last
> >> > PI, but
> >> > > how would I refer to possibly 2 or 3 PIs that are at the end
> >> of
> >> > the node
> >> > > (not knowing what they are or how many), but still process
> >PIs
> >> > that are
> >> > > contained elsewhere in this content?   Is there some syntax
> >> that
> >> > refers> to consecutive elements or refers to an element that
> >is
> >> > the last one in
> >> > > a node, not knowing what element it is?
> >> > >
> >> > > Here is explanation for what I'm trying to do:
> >> > >
> >> > > Process all content, unless they are PIs that occur
> >> > consecutively at the
> >> > > very end of the node.
> >> > >
> >> > > Then I have to insert an element, then process these PIs
> >that
> >> occur> > consecutively at the very end of the node.
> >> > >
> >> > > I'm having trouble narrowing down my research on this one.
> >> Does
> >> > anyone> have any ideas?
> >> > >
> >> > > Thanks,
> >> > > Emily


transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent