RE: [xsl] Displaying document( ) output within CDATA

Subject: RE: [xsl] Displaying document( ) output within CDATA
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Thu, 28 Jun 2001 12:05:09 +0100

Mike is right, this is an interesting requirement.

To refine and add to his comments:

Basically there are two ways to do this. One is, find some way of including the file as a literal, never parsing it. This would have to be managed some way *outside* the XSLT. This is what Mike is describing. Having a specialized output serializer, or a post-process, that would pick up a processing instruction, would be a good way to do it. (In the old days, this might have been handled with an external unparsed entity, not a processing instruction, but XSLT has no support for unparsed entities in output, and a PI can serve the same purpose).

Another approach is to do it the way you're thinking, with the document() function (thereby, as Mike remarks, incurring the overhead of parsing the file). To recreate the "markup" in your output is really the problem here -- the CDATA marked section you think you want in your output is actually a red herring. (It won't matter if your processor escapes each markup delimiter individually, which is what most will do.) Use a special mode to create this mock-markup, something like this:

if your source has

<example file="example.xml"/>

in your stylesheet:

<xsl:template match="example">
  <xsl:apply-templates select="document(@file)" mode="tagged"/>

<xsl:template match="*" mode="tagged">
  <xsl:value-of select="concat('&lt;', local-name())"/>
  <xsl:apply-templates select="@*" mode="tagged"/>
  <xsl:apply-templates select="node()" mode="tagged"/>
  <xsl:value-of select="concat('&lt;/', local-name(), '&gt;')"/>

<xsl:template match="@*" mode="tagged">
  <xsl:value-of select="concat(' ', local-name(), '=&quot;')"/>
  <xsl:value-of select="."/>
  <xsl:value-of select="'&quot;'"/>

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

Note well: this doesn't simply pop your file in. What it does is render the XML from the file (example.xml) in a kind of pseudo-markup. Attributes will probably not be in the order they are in the original, for example, since the parser isn't bound to respect that when it builds the tree.

Both for this reason (you won't get your file *literal* back) and for performance reasons, Mike's solutions are preferable. But if you *have* to do it in XSLT, it can be done. Handling comments, processing-instructions and namespaces are exercises I leave to you.


At 09:59 AM 6/28/01, Mike wrote:
Really, you want to avoid parsing the example XML in the first place, which
then reduces to the problem of loading a non-XML text file as a string
value. You can do this easily enough with an extension function, or with a
JAXP processor you could write a URIResolver that bypasses the parsing.

Another approach is to write your own serializer (subclassing or pipelining
into the standard one for your chosen processor). Then instead of reading
the example file into the transformation, the transformation can output a
processing instruction containing a reference to the file, and your
serializer can expand this reference by fetching the file and including its

Mike Kay
Software AG

Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.      
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
  Mulberry Technologies: A Consultancy Specializing in SGML and XML

XSL-List info and archive:

Current Thread