php xpath dealing with apostrophe / single quote i

2020-02-02 03:38发布

问题:

In my PHP script, I'm using XPATH to search nodes for text. Everything works swimmingly -except - when I search for a word with an apostrophe.

basically my code looks like this

$keyword = $_GET['keyword'];
...snip...
$xml = simplexml_load_file($data);


 $search = strtolower($keyword);
 $upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 $lower = "abcdefghijklmnopqrstuvwxyz";

$nodes = $xml-xpath("//line[contains(translate(text(),'$upper','$lower'),'$search')]");

again, all the above code works great - I can search for strings inside nodes and I get the correct matches back.

However, if a node looks like this: <line number="23">Shall I compare thee to a summer's day?</line>

and I search for summer's day...I get errors on the above $nodes line. What's more, if I search for "...summers" (no apos) the above line does not match. The only way to get the above line to return would be a search for "...summer" - which would include summer's.

I've tried stripslashes, addslashes, tohellwithslashes, htmlspecialchars but nothing works. Also, According to Google, in XPATH 1.0 (which I'm forced to use since this is PHP) I will NEVER be able to escape an apostrophe. Seriously?

So I turn to the geniuses here, someone MUST have had to deal with an XML file that they needed to traverse with XPATH in PHP that had an apostraphe! If XPATH can't do this, what can I do in PHP to get XPATH to return this node?

回答1:

As Google shared with you, you cannot escape an apostrophe in XPath. The simplest workaround is to use a different quote character around the string parts of the query.

$nodes = $xml->xpath('//line[contains(translate(text(),"'.$upper.'","'.$lower.'"),"'.$search.'")]');

Of course, the above is only useful if you don't want to allow double-quotes in the search value. If that might be necessary, then you could move the searching/comparison into PHP-land using the method that Gordon pointed out in your previous question.



回答2:

(which I'm forced to use since this is PHP)

perhaps http://basex.org/api might be worth a look/try. It allows you to use XQuery/XPath and communicates either via REST or sockets. Apart from that I'd recommend salathes solutions.



回答3:

Well i was in the same quest, and after a moment i found that's there is no support in xpath for this, quiet disappointing! But well we can always work around it!

I wanted something simple and straight froward. What i come with is to set your own replacement for the apostrophe, kind of unique code (something you will not encounter in your xml text) , I chose //apos// for example. now you put that in both your xml text and your xpath query . (in case of xml you didn't write always we can replace with replace function of any editor). And now how we do? we search normally with this, retrieve the result, and replace back the //apos// to '.

bellow some samples from what i was doing:

  function repalce_special_char_xpath($str){
    $str = str_replace("//apos//","'",$str);
    /*add all replacement here */
    return $str;
}

function xml_lang($xml_file,$category,$word,$language){ //path can be relative or absolute
    $language = str_replace("-","_",$language);// to replace - with _ to be able to use "en-us", .....
    $xml = simplexml_load_file($xml_file);
    $xpath_result = $xml->xpath("${category}/def[en_us = '${word}']/${language}");
    $result = $xpath_result[0][0];
    return repalce_special_char_xpath($result);
}

the text in xml file:

<def>
        <en_us>If you don//apos//t know which server, Click here for automatic connection</en_us>   <fr_fr>Si vous ne savez pas quelle serveur, Cliquez ici pour une connexion automatique</fr_fr>    <ar_sa>إذا لا تعرفوا أي سرفير, إضغطوا هنا من أجل إتصال تلقائي</ar_sa>
    </def>

and the call in the php file (generated html):

<span><?php echo xml_lang_body("If you don//apos//t know which server, Click here for automatic connection")?>