4

I'd like to be able to convert an apostrophe to the string ' using XSLT. I've got the following XML

<OrgName>King's College</OrgName>

I'd like to be able to output the following:

<OrgName>King&apos;s College</OrgName>

I've tried a character map but I don't think this works as you can only replace a single character with a string.

I've also tried a replace function but I'm not sure what I can do to make sure that the full string actually appears in the output file?

<xsl:value-of select='replace(OrgName,"&amp;apos;","&amp;apos;")' />

In my final solution I need to be able to replace all apostrophe's in the text rather than just for one node.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
JimS
  • 1,123
  • 3
  • 14
  • 17
  • 1
    ">I've tried a character map but I don't think this works as you can only replace a single character with a string." But replacing a character with a string is exactly what you are trying to do. Character maps can do this job, it seems you did something wrong. – Michael Kay May 03 '11 at 13:03
  • Good question, +1. See my answer for a complete, short and easy solution using character maps. :) – Dimitre Novatchev May 03 '11 at 13:09
  • Thanks for answers, I'll check if I can get them working. The reason I didn't think a character map would work is that I thought the apostrophe would be represented by the predefined entity ' even though it doesn't appear like that in the file. To me "'" looks like a string rather than a single character so I thought it wasn't possible. Perhaps I'm not understanding how entities work? I'm also confused about why I'm able to use the literal ' rather than the entity string in the original XML document. – JimS May 03 '11 at 15:57
  • Do note that both XML documents are the same from the point of view of a real XML consumer. –  May 03 '11 at 23:16
  • @Michael Kay - You're right, I was doing something wrong. The character map was working and outputting "'" Problem was I was then reparsing the output and building a JDOM document which was undoing my work. Now I'm just writing an output stream directly to a file from the transformation it works fine. – JimS May 13 '11 at 10:39

2 Answers2

3

Using a character map is as simple as this:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes" indent="yes" use-character-maps="mApos"/>

    <xsl:character-map name="mApos">
     <xsl:output-character character="&apos;" string="&amp;apos;"/>
    </xsl:character-map>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:copy-of select="." />
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<OrgName>King's College</OrgName>

the wanted, correct result is produced:

<OrgName>King&apos;s College</OrgName>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
0

This is only a partial answer:

For replacing the character ' you may use the following:

<xsl:value-of select="replace(xs:string(str), 
                              codepoints-to-string(39), 
                              '&amp;apos;')"/>

which requires XSLT/XPath 2.0. Explanation codepoints-to-string returns a string from a sequence of code points, and 39 corresponds to the character ''

For doing this replacement on every node of your XML ... I have no solution at the moment: will think about it.

Anyway, I hope this helps.

MarcoS
  • 13,386
  • 7
  • 42
  • 63