Re: [xsl] Cold Fusion

Subject: Re: [xsl] Cold Fusion
From: Mike Brown <mike@xxxxxxxx>
Date: Fri, 14 Mar 2003 10:48:03 -0700 (MST)
Christine Stamatis (s) wrote:
> That's exactly what I'm trying to do. My error, I didn't submit my initial
> inquiry properly.  I've been given an existing set of xsl/xml files which
> render html versions.  I've been asked to tweak the xsl in order to produce
> a .cfm rendition.
> 
> When I edit the xsl file in XMLSpy, I get the following validation error
> message: 
> 
> "This file is not well-formed: =expected after (CFIF IsDefined)"

Yes, as I mentioned, XSLT is XML, and thus must be well-formed. 

In XSLT templates you are not saying what literal text you want to produce in
your output; you are saying what nodes (information items) you want to produce
in a data structure (the result tree) from which some linear output (encoded
text that conforms to the HTML syntax, in your case) will be *automatically*
derived *after* the transformation is complete.

During the transformation, the result tree is constructed in an XML-friendly
way, regardless of the syntax you suggested (in xsl:output) for its
eventual serialization.

So for example if you are wanting to produce the output

  <p>hello world<hr noshade></p>

then you need to write it in the stylesheet as XML

  <p>hello world<hr noshade="noshade"/></p>

so that the result tree will have the structure

  |___element node named 'p'
        |___text node encapsulating 'hello world'
        |___element node named 'hr'
               \__attribute node named 'noshade' with value 'noshade'

The HTML serializer in the XSLT processor knows how to handle elements and
attributes that are defined in HTML 4.0. For attributes with certain names, it
will write them in minimized form (no value), and for elements that are not
supposed to have an end tag, it will write them without end tags, thus producing
the output you want:

  <p>hello world<hr noshade></p>

Unrecognized (non-HTML 4.0) elements are generally written in a generic
fashion, with end tags, and without any special treatment of their attributes.
If they are in a non-empty namespace, they'll be written in the XML syntax. So,
while you could have in your stylesheet

  <notHTML a="a"/>

it would come out looking like

  <notHTML a="a"></notHTML>

rather than

  <notHTML a>

For this reason, it is *impossible* to produce, with the built-in HTML
serializer,

   <CFIF IsDefined ("Cookie.ChocolateChip")>

from element and attribute nodes in the result tree. You simply can't do it.
Even if you could get the minimized IsDefined, you'd still be unable to
produce an attribute named '("Cookie.ChocolateChip")'. That's why I suggested
two alternative mechanisms that you could try.

> (The following is placed in the bottom of the document)
> <cfelse>
> 	<cflocation url="../../../notify.cfm">
> 	</cfif>

CFML was developed without any interest in compatibility with XML. Case
doesn't matter, apparently (CFIF in the opening tag vs cfif in the closing),
tag contents after the element name are not attribute name-value pairs
('IsDefined ("Cookie.ChocolateChip")' is a function call), and there's no need
for balance (closing tags are optional or impossible, and tags signal a change
of state in the parser rather than indicating structure). So producing XML
that can be automatically serialized in this horrid syntax is nigh on impossible.

Again, that's why I suggested either using the risky disable-output-escaping
feature of xsl:text and xsl:value-of, so that you can construct your CFML as a
single text node which is then serialized in a nonconformant syntax, or else
construct processing instruction nodes that you can then strip the question
marks out of when you're done.

> This may be a case for the use of disable-output-escaping, where you write
> all your tags as XML character data and then tell the serializer to emit
> them without escaping the markup characters "<" and "&":
> 
> <xsl:text disable-output-escaping="yes"><![CDATA[
> <!--- <CFIF IsDefined("URL.sys")> --->
> <CFIF IsDefined("Cookie.ChocolateChip")>
>       <cfinclude template="/CheckLogin.cfm">
>  <!--- <CFIF #Cookie.ChocolateChip# IS #URL.sys#> --->
> <cfelse>
>       <cflocation url="../../../register.cfm">
> </cfif>
> ]]></xsl:text>
> 
> but this kludgy "solution" is not guaranteed to work at all (its support is
> optional and relies on the processor serializing the result tree directly).
> See also http://www.dpawson.co.uk/xsl/sect2/N2215.html
> 
> My recommendation, if you must use XSLT, is to instead generate something
> that you can transform in an external, non-XSLT search-and-replace.
> 
> <xsl:processing-instruction target="cfif">
>   <xsl:text>IsDefined("Cookie.ChocolateChip")</xsl:text>
> </xsl:processing-instruction>
> <xsl:text>&#10;&#9;</xsl:text>
> <xsl:processing-instruction target="cfinclude">
>   <xsl:text>template="/CheckLogin.cfm"</xsl:text>
> </xsl:processing-instruction>
> 
> will generate
> 
> <?cfif IsDefined("Cookie.ChocolateChip")?>
>         <?cfinclude template="/CheckLogin.cfm"?>
> 
> which you can then do a simple replacement of "<?" and "?>"
> (to "<" and ">") on, outside of XSLT.

Mike

-- 
  Mike J. Brown   |  http://skew.org/~mike/resume/
  Denver, CO, USA |  http://skew.org/xml/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread