Subject: Re: [xsl] targeting the last element in a node or consecutive elements From: Chuck Bearden <cbearden@xxxxxxxx> Date: Thu, 4 Jan 2007 16:00:04 -0600 |
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
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] targeting the last elemen, egarrett | Thread | [xsl] undefined reference to `xmlXP, Nicolas Ecarnot |
Re: [xsl] undefined reference to `x, Florent Georges | Date | [xsl] Re: XML Tag to Output Math ty, Byomokesh |
Month |