How can I preserve entity references when transforming XML with XSLT (2.0)? With all of the processors I've tried, the entity gets resolved by default. I can use xsl:character-map
to handle the character entities, but what about text entities?
For example, this XML:
<!DOCTYPE doc [
<!ENTITY so "stackoverflow">
<!ENTITY question "How can I preserve the entity reference when transforming with XSLT??">
]>
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
transformed with the following XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
produces the following output:
<doc>
<text>Hello stackoverflow!</text>
<text>How can I preserve the entity reference when transforming with XSLT??</text>
</doc>
The output should look like the input (minus the doctype declaration for now):
<doc>
<text>Hello &so;!</text>
<text>&question;</text>
</doc>
I'm hoping that I don't have to pre-process the input by replacing all ampersands with &
(like &question;
) and then post-process the output by replacing all &
with &
.
Maybe this is processor specific? I'm using Saxon 9.
Thanks!
Best Answer
If you know what entities will be used and how they are defined, you can do the following (quite primitive and error-prone, but still better than nothing):
when applied on the provided XML document:
the wanted result is produced:
Do note:
The special (RegEx) characters in the replacements must be escaped.
We needed to resolve to DOE, which isn't recommended, because it violates the principles of the XSLT architecture and processing model -- in other words this solution is a nasty hack.