How to write an xpath to select a node whose text contains special characters such as apostorophe?

The Light picture The Light · Jan 20, 2012 · Viewed 7.9k times · Source

How to write an xpath to select a node whose text contains special characters such as ' which is kind of invalid inxpath?

<Nodes><Node><Text>General Marketing'</Text><Nodes><Node><Text>Brochures</Text></Node><Node><Text>Value-Added</Text><Nodes><Node><Text>About Henderson</Text></Node><Node><Text>Own the World</Text></Node></Nodes></Node></Nodes></Node></Nodes>

and

var branchName = "General Marketing'";
var xPath = String.Format("/Nodes/Node[Text = '{0}']", branchName);

the above xpath fails because the xPath contains the below text:

/Nodes/Node[Text = 'General Marketing''] 

As you can see there are 2 apostorophes.

From my tests so far it only has problem with '. Not sure whether there are any other special characters that it may have issue with?

So I guess I'd need to modify my xpath to be something else.

I tried the below but didn't work:

var xPath = String.Format("/Nodes/Node[Text = \"{0}\"]", branchName);

Hope the question is clear.

Thanks,

Answer

Dimitre Novatchev picture Dimitre Novatchev · Jan 20, 2012

Use:

//Text[.="General Marketing'"]

If this XPath expression is used in XSLT, then the whole XPath expression myst be surrounded by apostrophes and the last character (apostrophe) ofthe string surrounded by quotes must be escaped using the built-in entity &apos;:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select='//Text[.="General Marketing&apos;"]'/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<Nodes>
    <Node>
        <Text>General Marketing'</Text>
        <Nodes>
            <Node>
                <Text>Brochures</Text>
            </Node>
            <Node>
                <Text>Value-Added</Text>
                <Nodes>
                    <Node>
                        <Text>About Henderson</Text>
                    </Node>
                    <Node>
                        <Text>Own the World</Text>
                    </Node>
                </Nodes>
            </Node>
        </Nodes>
    </Node>
</Nodes>

the wanted element is selected and copied to the output:

<Text>General Marketing'</Text>

This is simpler than are other approaches such as:

//Text[. = concat('General Marketing', $vQ)]

where the variable $vQ is defined as:

<xsl:variable name="vQ">'</xsl:variable>