Re: Transforming HTML to NITF
Hi Adam, >> I need to work with thos tags that have the | beside them as a single >> block so that I can wrap the entire thing in a <p> tag. Since I don't know >> the placement or the order or even the frequency of such situations (there >> is no reason why I couldn't have more blocks that need to be grouped >> together). The solution needs to be general. Here's a single-pass solution that steps through the nodes one by one to work out what to do. The first thing to do is get rid of all that insignificant whitespace - otherwise you'll get lots of paragraphs containing nothing but whitespace: <xsl:strip-space elements="*" /> The next is to set the thing going with a body-matching template. This creates a copy of the body and then starts the ball rolling by applying templates to its first child: <xsl:template match="body"> <body> <xsl:apply-templates select="node()" /> </body> </xsl:template> Now, if apply templates like this comes across something that you want to keep as it is, then you just want to copy it before moving on to the next node. Here I've just listed the elements that you said were valid directly under a body element: <xsl:template match="p|table|ul|ol"> <xsl:copy-of select="." /> <xsl:apply-templates select="following-sibling::node()" /> </xsl:template> Now, when you come across something else, you want to create a p element and place the next bunch of misfits inside it. Creating the p element is easy. Inside it, I apply templates to the current node in 'copy' mode. 'copy' mode is my mode for copying the misfits and moving on to the next. Then I apply templates to the next sibling that's one of the acceptable elements: <xsl:template match="*|text()"> <p> <xsl:apply-templates select="." mode="copy" /> </p> <xsl:apply-templates select="following-sibling::*[self::p or self::table or self::ul or self::ol]" /> </xsl:template> For 'copy' mode, I want to make a copy of the matched node, and then move on to the next, but only if the next is a misfit node, not if it's acceptable. I could have done it with a big XPath, but it's a bit clearer to use an xsl:if: <xsl:template match="*|text()" mode="copy"> <xsl:copy-of select="." /> <xsl:if test="not(following-sibling::node()[self::p or self::table or self::ul or self::ol])"> <xsl:apply-templates select="following-sibling::node()" mode="copy" /> </xsl:if> </xsl:template> [Aside: I think that's the first time I've used a stepping-through solution to one of these problems. Usually I use a Muenchian method, keying on the preceding acceptable element. This way is actually a lot smoother and easier to understand.] As Mike suggested, you might want to do a two-pass solution in which you essentially label the nodes that are 'misfits' as opposed to those that are valid in the context. That makes it a little easier to know which node to move on to next. I hope that helps, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
PURCHASE STYLUS STUDIO ONLINE TODAY!
Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!
Download The World's Best XML IDE!
Accelerate XML development with our award-winning XML IDE - Download a free trial today!
Subscribe in XML format