xsl-list
[Top] [All Lists]

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

2007-01-04 15:14:06
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(_at_)rice(_dot_)edu                                        PO Box 1892
AIM: Schleifheim                              Houston, TX 77251-1892
713.348.3661 (voice) --- <http://cnx.org/> ------ (fax) 713.348.3665

From: egarrett(_at_)cinci(_dot_)rr(_dot_)com 
<egarrett(_at_)cinci(_dot_)rr(_dot_)com>
Date: Jan 4, 2007 2:42 PM
Subject: Re: [xsl] targeting the last element in a node or consecutive 
elements
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com


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(_at_)cinci(_dot_)rr(_dot_)com>
Date: Thursday, January 4, 2007 2:21 pm
Subject: Re: [xsl] targeting the last element in a node or consecutive
elements
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com

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(_at_)cinci(_dot_)rr(_dot_)com
Date: Thursday, January 4, 2007 9:59 am
Subject: Re: [xsl] targeting the last element in a node or
consecutive
elements
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com

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(_dot_)online(_at_)xs4all(_dot_)nl>
Date: Thursday, January 4, 2007 9:53 am
Subject: Re: [xsl] targeting the last element in a node or
consecutive
elements
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com

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(_dot_)Garrett(_at_)thomson(_dot_)com 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

--~----------------------------------------------------------
--
--
----
XSL-List info and archive:
http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--







--~------------------------------------------------------------
--
--
--
XSL-List info and archive:
http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


--~--------------------------------------------------------------
--
--
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--