Using regex to filter attributes in xpath with php

前端 未结 2 1265
不思量自难忘°
不思量自难忘° 2020-11-29 11:56

I am trying to filter html tables with regex matching their id attribute. What am i doing wrong? Code i am trying to implement:

        $this->xpath =          


        
相关标签:
2条回答
  • 2020-11-29 12:16

    An attribute is still a complex element according to DOM (has a namespace etc.). Use:

    //table[php:function('preg_match', '/post\d+/', string(@id))]
    

    Now, we need a boolean return, so:

    function booleanPregMatch($match,$string){
        return preg_match($match,$string)>0;
    }
    $xpath->registerPHPFunctions();
    foreach($xpath->query("//table[@id and php:function('booleanPregMatch', '/post\d+/', string(@id))]") as $key => $row){
         echo $row->ownerDocument->saveXML($row);
    }
    

    BTW: for more complex issues, you can of course sneakily check what's happening with this:

    //table[php:function('var_dump',@id)]
    

    It's a shame we don't have XPATH 2.0 functions available, but if you can handle this requirement with a more unreliable starts-with, I'd always prefer that over importing PHP functions.

    0 讨论(0)
  • 2020-11-29 12:24

    What am i doing wrong?

    The xpath expression @id (second parameter) returns an array but preg_match expects a string.

    Convert it to string first: string(@id).

    Next to that you need to actually compare the output to 1 as preg_match returns 1 when found:

    foreach($xpath->query("//table[@id and 1 = php:function('preg_match', '/post\d+/', string(@id))]") as $key => $row)
    {
        var_dump($key, $row, $row->ownerDocument->saveXml($row));
    }
    

    Explanation/What happens here?:

    A xpath expression will by default return a node-list (more precisely node-set). If you map a PHP function onto such expressions these sets are represented in form of an array. You can easily tests that by using var_dump:

    $xpath->query("php:function('var_dump', //table)");
    
    array(1) {
      [0]=>
      object(DOMElement)#3 (0) {
      }
    }
    

    Same for the xpath expression @id in the context of each table element:

    $xpath->query("//table[php:function('var_dump', @id)]");
    
    array(1) {
      [0]=>
      object(DOMAttr)#3 (0) {
      }
    }
    

    You can change that into a string typed result by making use of the xpath string function:

    A node-set is converted to a string by returning the string-value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned.

    $xpath->query("//table[php:function('var_dump', string(@id))]");
    
    string(4) "test"
    

    (the table has id="test")

    0 讨论(0)
提交回复
热议问题