[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: XML/XHTML fragment to text

Subject: Re: XML/XHTML fragment to text
From: "Abel Braaksma (online)" <abel.online@xxxxxxxxx>
Date: Fri, 10 Aug 2007 13:03:16 +0200 (CEST)
Re:  XML/XHTML fragment to text
> XSL is awsome when you work with XML in and out, but trying to output
> text... it's doesn't look so easy and natural !
>

XSLT is awesome when you want to output text,  too. What you are trying is
outputting XML as if it were text, and that is something different. Normally,
when you serialize an XML tree it will be output as text (XML text). Inputting
 XML  and trying to output it as text that looks the same as XML can be done
much easier: <xsl:copy-of select="/" /> and output method="xml".

Provided that you have a reason for using this method, here're some comments
on your XSLT. I don't know why it does not output what you want, as it does
output the input as was already mentioned by somebody else. What changes do
you expect?

> So the problem is : converting an XHTML (in fact any XML) fragment to text.
>

Use the serialized XML, really.

>
>     <xsl:output method="text" encoding="utf-8"
> omit-xml-declaration="yes" indent="no"/>

when you output as text the omit-xml-declaration and the indent attribute have
no effect.

>         <xsl:variable name="xhtml"><xsl:apply-templates
> select="fragment"/></xsl:variable>
>
>        <!-- And we output the text -->
>         <xsl:value-of select="$xhtml"/>

If all you do with a variable is selecting it's value, you can rewrite  the
above just as easy as:

<xsl:apply-templates select="fragment" />

>     <xsl:template match="fragment//element()">

element() is an XSLT 2.0 feature and does not exist in XSLT 1.0. Use * instead.

It is considered bad practice to use // in expressions like this, because it
requires the processor to lookup the whole tree to the root to see if an
element has an ancestor 'fragment'. It's probably much faster and even easier
to use modes instead.

>         <xsl:choose>
>         <!-- for not empty elements -->
>             <xsl:when test="*|text()">
>                 <xsl:text>&lt;</xsl:text>
>                 <xsl:value-of select="name(.)"/>
>                 <xsl:apply-templates select="@*"/>
>                 <xsl:text>&gt;</xsl:text>
>                 <xsl:apply-templates select="*|text()"/>
>                 <xsl:text>&lt;/</xsl:text>
>                 <xsl:value-of select="name(.)"/>
>                 <xsl:text>&gt;</xsl:text>
>             </xsl:when>
>         <!-- for empty elements -->
>             <xsl:otherwise>
>                 <xsl:text>&lt;</xsl:text>
>                 <xsl:value-of select="name(.)"/>
>                 <xsl:apply-templates select="@*"/>
>                 <xsl:text>/&gt;</xsl:text>
>             </xsl:otherwise>
>         </xsl:choose>

Above you make a distinction between elements that should not be necessary. An
empty element is equal when written as <p /> or <p></p>. However, XHTML in
browsers can have some trouble with interpretation. Instead  of the verbose
xsl:choose, I'd go for the following matching templates, it will prove easier
and better maintainable than long winded xsl:chooses:

<xsl:template match="*[not(*|text())]" mode="text-xml">
   ... empty elem treatment
</

<xsl:template match="*" mode="text-xml">
   ... filled elem treatment
</

you may want  to make the empty element treatment to be explicit for br, meta,
etc, and make sure that it does not accidentally make script, p, div etc empty
with the minimized tag, because that will look bad in several user agents.

>
>     <xsl:template match="fragment//text()">
>         <xsl:value-of select="."/>
>     </xsl:template>

The  above actually isn't necessary, the default template for text() is to
output it as text. But then again, it is good practice to make it explicit.

of course, do not use the fragment// here either, instead do: <xsl:template
match="text()" mode="text-xml" >...

>
>     <xsl:template match="fragment//@*">

same here, I recommmend removing the fragment// and make it <xsl:template
match="@*" mode="text-xml" >...



All in all, you are making an input == output where you basically skip
redundant information, *and* you are creating your own specific XHTML
processor (which may come in handy for some people that still use XSLT 1.0 and
try to make sound XHTML with it).

Cheers,
-- Abel Braaksma

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.