Subject: Re: [xsl] RE: How to transform <BR> to </P><P> From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Fri, 19 Jan 2001 15:49:40 +0000 |
Hi Chris, > There are more than <BR> and text() as children of <TEXT>. And I > wish to break the text into paragraphs only when it reaches a <BR > TYPE="END">. I'm not sure what the best way of doing this is, but this is the method that I usually use. Basically, this is a grouping problem. You want to group all the nodes within the TEXT element according to which BR[@TYPE = 'END'] they come after and place each group within a P element. If you apply templates just to the BR[@TYPE = 'END'] elements, then you can gather the relevant content for the paragraph at that point: you know that there need to be as many paragraphs as BR[@TYPE = 'END'] elements (of course as long as they're preceded by some content). So a template that takes a BR[@TYPE = 'END'] element and outputs a paragraph of the content preceding it would look something like: <xsl:template match="BR[@TYPE = 'END']"> <!-- locate the preceding BR --> <xsl:variable name="br-before" select="preceding-sibling::BR[@TYPE = 'END'][1]" /> <!-- the content are those nodes that come before this one and after the preceding BR --> <xsl:variable name="content" select="preceding-sibling::node() [not($br-before) or generate-id(preceding-sibling::BR [@TYPE = 'END'][1]) = generate-id($br-before)]" /> <!-- if there are any nodes in that list --> <xsl:if test="$content"> <!-- output a paragraph --> <P> <!-- with a copy of those nodes as the content --> <xsl:apply-templates select="$content" /> </P> </xsl:if> </xsl:template> To make this work properly, you need to only apply templates to those BR elements: <xsl:apply-templates select="BR[@TYPE = 'END']" /> You also need to create a paragraph for any stray text at the end of the TEXT element that *doesn't* have a BR[@TYPE = 'END'] following it: <xsl:variable name="end-content" select="node()[not(self::BR[@TYPE = 'END']) and not(following-sibling::BR [@TYPE = 'END'])]" /> <xsl:if test="$end-content"> <P> <xsl:apply-templates select="$end-content" /> </P> </xsl:if> These both need to go within a template that matches the TEXT element: <xsl:template match="TEXT"> <xsl:apply-templates select="BR[@TYPE = 'END']" /> <xsl:variable name="end-content" select="node()[not(self::BR[@TYPE = 'END']) and not(following-sibling::BR [@TYPE = 'END'])]" /> <xsl:if test="$end-content"> <P> <xsl:copy-of select="$end-content" /> </P> </xsl:if> </xsl:template> Finally, to ignore all that irrelevant whitespace, you need to strip spaces within the TEXT element: <xsl:strip-space elements="TEXT" /> This does the grouping that you're after. There are other ways of doing it - in particular you could use Muenchian grouping with keys in order to achieve the same effect. You can also write a recursive to template to do collect the relevant nodes for the paragraph content. I haven't addressed outputting the character entity - I think you know how to do that from last time - or turning the AUTOITALIC element into an ITALIC element, which you should be able to do yourself, I think? I hope that helps anyway, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] RE: How to transform <BR>, Sun, Christine (Cah | Thread | [xsl] write out '&' instead of '&am, Sun, Christine (Cah |
Re: [xsl] problem with Passing Para, David Carlisle | Date | Re: [xsl] Images and XSL FO, Paul Grosso |
Month |