xsl-list
[Top] [All Lists]

Re: [xsl] Removing namespaces without escaping CDATA???

2007-04-09 12:36:28
Mukul Gandhi wrote:
On 4/9/07, G. Ken Holman <gkholman(_at_)cranesoftwrights(_dot_)com> wrote:
No ... remember that the emitted result tree cannot be addressed in
any fashion and the distinction between the different contexts of "y"
in the result tree is, effectively, trying to address the result tree
to know "where am I now in the result tree?" in order to selectively
apply the serialization rule.

Note in XSLT 2.0 Section 20 and XSLT 1.0 Section 16 that the data
type of the cdata-section-elements is just a white-space-separated
list of QNames ... there is no opportunity to specify context for each one.

When I said, I want CDATA section to appear at location /x/p/q/y, my
intention was to specify the location (using a syntax which is
familiar). You rightly said, result tree cannot be addressed. I am
aware of this fact.

For somebody, CDATA section could be useful at location /x/p/q/y, and
not at location /x/y. But this cannot be achieved, with current syntax
<xsl:output cdata-section-elements="qnames" />.

I suggested an improvement to the xsl:element instruction, with
<xsl:element name="qname" cdata-section="yes | no" .. As Mike said,
this is architecturally bad from XSLT processor design point of view
(but is it that bad?). But it seems to be an useful feature from end
user's point of view.


Hmm, not really an improvement, but when things "cannot be done" and when "things" cover a rather unusual request, I tend to try a rather unusual approach to solving it. If you want this, really, you don't need any d-o-e on elements, or implementation specific extension attributes. If you'd feel comfortable with using functions or call-template to achieve this goal, here's how, in plain portable XSLT 2.0 syntax (it is fairly straightforward):

<xsl:output use-character-maps="cdata" />

<xsl:character-map name="cdata">
   <xsl:output-character character="&#xE0F1;" string="&lt;![CDATA["/>
   <xsl:output-character character="&#xE0F2;" string="]]>"/>
   <xsl:output-character character="&#xE0F3;" string="&lt;"/>
   <xsl:output-character character="&#xE0F4;" string="&amp;"/>
</xsl:character-map>

<xsl:template match="/">
<xsl:copy-of select="f:make-cdata('my-cdata', 'less-then &lt; and ampersand: &amp;')" />
</xsl:template>

<xsl:function name="f:make-cdata">
   <xsl:param name="elem-name" />
   <xsl:param name="content" />
   <xsl:element name="{$elem-name}">
       <xsl:text>&#xE0F1;</xsl:text>
<xsl:sequence select="replace(replace($content, '&lt;', '&#xE0F3;'), '&amp;', '&#xE0F4;')" />
       <xsl:text>&#xE0F2;</xsl:text>
   </xsl:element>
</xsl:function>

<!-- output of the above -->
<my-cdata><![CDATA[less-then < and ampersand: &]]></my-cdata>


Not that I consider this good coding, but it offers a solution to your request (having control on which elements receive 'CDATA treatment'). I just want to show you that you can get it any way you'd like with the current possibilities of XSLT/XPath 2.0. Use xsl:output if the elements are static, use xsl:result-document if they are dynamic, use the above approach if you want full control.

I know, in your post you say you want to give some kind of xpath or similar that points to the elements that need be escaped. This is most easiest achieved with either a micro-pipeline (take your whole output and process it again using the above function, but only for the required elements) or an extra cycle.

Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

PS: not that with xsl:result-document all attributes are AVTs, _except_ use-character-maps (taking multiple qnames), which means that you have to choose your character mappings carefully to prevent collisions.

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--