This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: searching and replacing
- From: Mike Brown <mike at skew dot org>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Fri, 31 May 2002 01:30:32 -0600 (MDT)
- Subject: Re: [xsl] searching and replacing
- Reply-to: xsl-list at lists dot mulberrytech dot com
normbishop1@netscape.net wrote:
> I have written a template to search for any string containing <sub> or <sup> and to do subscript and superscript accordingly. The template works fine (I think)...
>
Yiks. You have many problems in the stylesheet you posted.
You apparently...
1. think that there is no difference between the literal text-and-markup of
the document and the XPath/XSLT node tree that is implied by it;
2. are trying to produce an exact copy of your input. That is,
<sub>foo</sub> in becomes <sub>foo</sub> out;
3. think the match pattern in a template causes nodes to be processed, rather
than just designating the template as being eligible to process a node that
matches the given pattern, *if* such a node happens to be selected for
processing via xsl:apply-templates or xsl:for-each;
4. think there are 'address' elements in your source tree, when there are
in fact none;
5. think xml:space="preserve" in your stylesheet is beneficial;
6. made a typo when you put 2 ending quotes on one of your namespace
declarations;
I'm not going to bother explaining all the things you should get from a good
book on XSLT, but I will show you a stylesheet that demonstrates the
principles you should be aware of. Against the source document you posted, use
a stylesheet that looks like this:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- when processing the root node, go process the element
children of 'chapter' element children of the 'document'
element child of the root node. this template is optional,
but saves a few cycles. -->
<xsl:template match="/">
<xsl:apply-templates select="document/chapter/*"/>
</xsl:template>
<!-- when processing a 'sub' element, make a 'subOut' element -->
<xsl:template match="sub">
<subOut>
<!-- go process the children of the current 'sub' -->
<xsl:apply-templates/>
</subOut>
</xsl:template>
<!-- when processing a 'sup' element, make a 'supOut' element -->
<xsl:template match="sup">
<supOut>
<!-- go process the children of the current 'sup' -->
<xsl:apply-templates/>
</supOut>
</xsl:template>
<!-- I have no idea what you're trying to do with 'line1','line2',etc.
so I will just guess that you want to flatten the structure and
see only the non-whitespace-only text content. For this we don't
even need to bother matching the 'line1' element.. just let the
built-in templates kick in and take us to the text nodes. -->
<!-- when processing a text node that is a child of an element whose
name starts with 'line', copy it to the result tree
as long as it has some non-whitespace text -->
<xsl:template match="*[starts-with(local-name(),'line')]/text()">
<xsl:if test="normalize-space()">
<xsl:copy/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
To help understand why it works the way it does, read the XPath spec where it
talks about the data model, and the XSLT spec where it talks about built-in
templates.
- Mike
____________________________________________________________________________
mike j. brown | xml/xslt: http://skew.org/xml/
denver/boulder, colorado, usa | resume: http://skew.org/~mike/resume/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list