Escaping Strings in XPath 1.0

XPath is a language for selecting nodes from an XML document. XPath is used extensively in XSLT and other XML technologies. I also vastly prefer using XPath (e.g. with XPathNavigator) over the XML DOM when manipulating XML in a non-streaming fashion.

In XPath, strings must be delimited by either single or double quotes. Given a quote character used to delimit a string, one can’t represent that same quote character within the string. This means that if you decide to use single quotes to delimit your XPath string, you couldn’t represent the string O’Reilly; use double quotes, and you can’t represent “Hello”.

However, given a quote delimiter, you can represent the other quote character. We can use this observation along with the concat XPath function to devise a general quoting rule for XPath strings. It’s easiest to show this via a series of examples:

Original String Quoted XPath String
a 'a' (or "a")
O'Reilly "O'Reilly"
"Hello" '"Hello"'
"Hello, Mr. O'Reilly" concat('"Hello, Mr. O', "'Reilly", '"')

Below is a piece of C++ code which implements these quotation rules:

std::string
QuoteXPathString(const std::string& xpath)
{
    // If we don’t have any single or double-quote characters, quote the
    // expression in single quotes.
    std::string::size_type pos = xpath.find_first_of("’\"");
    if (pos == std::string::npos)
        return "’" + xpath + "’";
     
    // If we cannot find the alternate quotation character, quote the
    // expression in the alternate quotation character.
    char chOther = (xpath[pos] == ‘"’ ? ‘\’‘ : ‘"’);
    pos = xpath.find(chOther, pos + 1);
    if (pos == std::string::npos)
        return chOther + xpath + chOther;
     
    // The string has both quotation characters.  We need to use concat()
    // to form the string.
    std::stringstream ss;
    ss << "concat("
       << chOther
       << xpath.substr(0, pos)
       << chOther;
    do {
        chOther = (xpath[pos] == ‘"’ ? ‘\’‘ : ‘"’);
        std::string::size_type pos2 = xpath.find(chOther, pos + 1);
        ss << ‘,’
           << chOther
           << xpath.substr(pos, pos2 – pos)
           << chOther;
        pos = pos2;
    } while (pos != std::string::npos);
    ss << ")";
     
    return ss.str();
}

Usage looks like:

std::string lastName = …; // May come from user input
std::string xpath = "//Customer[LastName = " +
    QuoteXPathString(lastName) + "]";

About Steven Engelhardt, CFA, AIF
Adjunct Professor of Software Engineering at DePaul University • Software Engineering, Data & Analytics in FinTech • Lives in Chicago, IL

One Response to Escaping Strings in XPath 1.0

  1. SandipW. says:

    Thanks for working code.
    I used it for below XPATH Query.

    Original String : Test ‘ both ” quotes”::LGC
    Quoted XPath String : “Value[@Name=concat(\”Test ‘ both \”,’\” quotes\”::LGC’)]”

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s