XSLT – munging apostrophes
Tuesday, 14 July 2009
Escaping escapes can be a near impossible task with XSLT.
Here is the standard form of testing whether a string matches
<xsl:if
test=”countryName=’USA’” >
Name matches
</xsl:if>
What happens if the country name is People’s Republic of China instead?
- You can’t use the apostrophe because the single quote is already used to delimit the string.
- You can’t use double quotes around the string because it is already used to delimit the attribute
- You can’t use the ' entity because it is converted to a single quote inside the attribute, so the attribute sees 'People's Republic of China' any way (which is an illegal expression).
Solution 1 – use string concatenation
<xsl:if
test=”countryName=concat(‘People,’, "'", ’s Republic of China’)” >
Name matches
</xsl:if>
Solution 2 – use a variable
<xsl:variable name=”apos”>'</xsl:variable>
<xsl:if
test=”countryName=concat(‘People,’, $apos, ’s Republic of China’)” >
Name matches
</xsl:if>
Solution 3 – thanks Jörn Horstmann
<xsl:variable name=”PRC”>People's Republic of China</xsl:variable>
<xsl:if
test=”countryName=$PRC” >
Name matches
</xsl:if>
You should follow me on twitter here
No. 1 — July 14th, 2009 at 10:25 pm
it is generally a bad idea to use a language (xslt here) which demands that you regularly put the very expressions that carry your programmatic intent into ‘escrow’ so to speak. i think it is bad language design. in this case, it is an outflow of the abuse of xml to express procedural content. look, the problems do not start at the apostrophe. they start when you have to put ‘if’ into pointy brackets. xml is so ‘stupid’, it can’t parse the word ‘if’, so to speak. i’ve seen shell scripts that call php that contains sql and so on, and i always tell people don’t but people won’t listen. using plain xml can be a pretty bad idea, but using xml to express a program that processes xml is worse. you want to have a decent, readable declarative language or a decent, readable procedural language for that purpose. xml is neither.
No. 2 — July 15th, 2009 at 6:16 am
How about using a variable to hold the string to compare, like this
People’s Republic of China
Name matches
No. 3 — July 15th, 2009 at 9:17 am
@love-encounter-flow XPath expressions inside XSLT is one of the warts in XSLT. Otherwise, we are so deeply invested already there was no choice but to workaround the problems. By the way, one saving grace of XSLT is that it’s actually a functional language, with no mutation allowed.
@Jörn yes that would work. I think WP swallowed your XML tags. I’ve included your solution in the post.
No. 4 — July 20th, 2009 at 11:13 am
Can’t you use
test=”countryName="People’s Republic of China"”
or
test=’countryName=”People's Republic of China”‘
?
BTW would you please consider providing an RSS feed with full articles on Planet Python?
No. 5 — July 20th, 2009 at 11:15 am
Yikes, the comment form interpreted my examples as HTML markup. Talk about metal-level confusion. I meant (and, since your blog has no ‘Preview’ button, can only hope that this’ll work):
test=”countryName="People’s Republic of China"”
and
test=’countryName=”People's Republic of China”‘
No. 6 — July 20th, 2009 at 6:28 pm
Solution 4 – use apostrophes for attribute value
No. 7 — July 20th, 2009 at 6:30 pm
(WP ate the example)