This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: How to transform an & ?


Thorbjørn Ravn Andersen wrote:
> I have tried several means of changing an & into & 
> (in order to have the webserver in the end output & instead of &),
> but it appears that both Xalan and Saxon ignores redefintions like 
> 
> 	<!ENTITY amp '<![CDATA[&amp;amp;]]>'>
> 
> in the DTD (which is overkill, but that was just to get started).
> 
> What is the correct way to change this?

It is the XML parser, not the XSLT processor, that is concerned with
entity declarations. Xalan and SAXON do not see entity references.

The XML spec says

"well-formed documents need not declare any of the following entities:
amp, lt, gt, apos, quot."

and then goes on to say:

"For interoperability, valid documents should declare the entities amp,
lt, gt, apos , quot, in the form specified in 4.6 Predefined Entities."

Section 4.6 says:

"All XML processors must recognize these entities whether they are
declared or not." and "If the entities lt or amp are declared, they must
be declared as internal entities whose replacement text is a character
reference to the character being escaped"

It's not entirely clear whether you can redefine amp to be some character
other than the ampersand character, but at the very least, you are
restricted to defining it to be a *single* character.

So...

I think you really need to think more about what it is that you want to
accomplish. 

"&amp;" in the XML/XSL becomes "&" in the source and result trees. "&" in
the result tree is usually serialized as "&amp;" by the XSLT processor
when the output method is html or xml and when the node wasn't created
with the disable-output-escaping flag set.

Given that you can't change the definition of amp for the XML and XSL
documents, and that you can't completely control how the XSLT processor
outputs "&" in the trees, you're kind of stuck with 2 options. 

1. post-process the output HTML, substituting & for &amp;.

2. in your XSL, whenever you need to create a text node, call a named
template that will substitute "&" characters in the text (designated by
"&amp;" in the stylesheet) with "&amp;" (designated by "&amp;amp;" in the
stylesheet).

<xsl:template name="amp2ampamp">
	<xsl:param name="StringToTransform"/>
	<xsl:choose>
		<xsl:when test="contains($StringToTransform,'&amp;')">
			<xsl:value-of select="concat(substring-before($StringToTransform,'&amp;'),'&amp;amp;')"/>
			<xsl:call-template name="amp2ampamp">
				<xsl:with-param name="StringToTransform" select="substring-after($StringToTransform,'&#xA;')"/>
			</xsl:call-template>
		</xsl:when>
		<xsl:otherwise>
			<xsl:value-of select="$StringToTransform"/>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>

Call the template like this:

<xsl:call-template name="amp2ampamp">
	<xsl:with-param name="StringToTransform" select="'1 &amp; 2 are &lt; 3'"/>
</xsl:call-template>

Or like this:
<xsl:call-template name="amp2ampamp">
	<xsl:with-param name="StringToTransform">
		<!-- stuff that generates text -->
		<xsl:value-of select="foo"/>
	</xsl:with-param>
</xsl:call-template>



   - Mike
____________________________________________________________________
Mike J. Brown, software engineer at         My XML/XSL resources:
webb.net in Denver, Colorado, USA           http://www.skew.org/xml/


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]