【问题标题】:Can I find exact match using phpQuery?我可以使用 phpQuery 找到完全匹配吗?
【发布时间】:2013-03-31 21:08:59
【问题描述】:

我使用 phpQuery 制作了一个脚本。该脚本会找到包含某个字符串的 td:

$match = $dom->find('td:contains("'.$clubname.'")');

到现在为止效果很好。因为一个俱乐部名称是例如奥地利 Lustenau,而第二个俱乐部名称是 Lustenau。它将选择两个俱乐部,但它应该只选择 Lustenau(第二个结果),所以我需要找到一个包含完全匹配的 td。

我知道 phpQuery 正在使用 jQuery 选择器,但不是全部。有没有办法使用 phpQuery 找到完全匹配?

【问题讨论】:

    标签: php jquery phpquery


    【解决方案1】:

    可以用filter来做,但是不漂亮:

    $dom->find('td')->filter(function($i, $node){return 'foo' == $node->nodeValue;});
    

    但是,css和xpath之间来回切换也不是

    【讨论】:

      【解决方案2】:

      我知道这个问题很老,但我已经根据hek2mgl 的回答编写了一个函数

      <?php
      
      // phpQuery contains function
      
      /**
      * phpQuery contains method, this will be able to locate nodes
      * relative to the NEEDLE
      * @param string element_pattern
      * @param string needle
      * @return array
      */
      function contains($element_pattern, $needle) {
      
          $needle = (string) $needle;
          $needle = trim($needle);
      
          $element_haystack_pattern = "{$element_pattern}:contains({$needle})";
          $element_haystack_pattern = (string) $element_haystack_pattern;
      
          $findResults = $this->find($element_haystack_pattern);
      
          $possibleResults = array();
      
          if($findResults && !empty($findResults)) {
              foreach($findResults as $nodeIndex => $node) {
                  if($node->nodeValue !== $needle) {
                      continue;
                  }
                  $possibleResults[$nodeIndex] = $node;
              }
          }
      
          return $possibleResults;
      
      }
      
      ?>
      

      用法

      <?php
      
      $nodes = $document->contains("td.myClass", $clubname);
      
      ?>
      

      【讨论】:

        【解决方案3】:

        更新:有可能,看@pguardiario的回答


        原始答案。 (至少是另一种选择):

        不,很遗憾,使用 phpQuery 是不可能的。但是使用 XPath 可以轻松完成。

        假设您必须遵循 HTML:

        $html = <<<EOF
        <html>
          <head><title>test</title></head>
          <body>
            <table>
              <tr>
                <td>Hello</td>
                <td>Hello World</td>
              </tr>
            </table>
          </body>
        </html>
        EOF;
        

        使用以下代码查找与 DOMXPath 的完全匹配:

        // create empty document 
        $document = new DOMDocument();
        
        // load html
        $document->loadHTML($html);
        
        // create xpath selector
        $selector = new DOMXPath($document);
        
        // selects all td node which's content is 'Hello'
        $results = $selector->query('//td[text()="Hello"]');
        
        // output the results 
        foreach($results as $node) {
            $node->nodeValue . PHP_EOL;
        }
        

        但是,如果您真的需要 phpQuery 解决方案,请使用以下内容:

        require_once 'phpQuery/phpQuery.php';
        
        // the search string
        $needle = 'Hello';
        
        // create phpQuery document
        $document = phpQuery::newDocument($html);
        
        // get matches as you suggested
        $matches = $document->find('td:contains("' . $needle . '")');
        
        // empty array for final results
        $results = array();
        
        // iterate through matches and check if the search string
        // is the same as the node value
        foreach($matches as $node) {
            if($node->nodeValue === $needle) {
                // put to results
                $results []= $node;
            }
        }
        
        // output results
        foreach($results as $result) {
            echo $node->nodeValue . '<br/>';
        }
        

        【讨论】:

        • 谢谢,这是我正在寻找的解决方案!我根据自己的进一步需求对其进行了一些更改,现在它很完美!
        • 另一个重要提示:无法像使用 jQuery 过滤功能那样仅使用 phpQuery 找到完全匹配
        • 嗯,好的。我不确定,但我也这么认为。这就是为什么我为此使用了第二个 foreach 循环(应该或多或少相同)......
        • 不是我的.. 没有理由
        • 很想知道原因,找不到。
        【解决方案4】:

        我没有 phpQuery 的经验,但 jQuery 会是这样的:

        var clubname = 'whatever';
        var $match = $("td").map(function(index, domElement) {
            return ($(domElement).text() === clubname) ? domElement : null;
        });
        

        phpQuery 文档表明-&gt;map() 可用,并且它接受回调函数的方式与在 jQuery 中相同。

        我相信您将能够执行到 phpQuery 的翻译。

        编辑

        这是我基于 5 分钟阅读的尝试 - 可能是垃圾,但这里是:

        $match = $dom->find("td")->map(function($index, $domElement) {
            return (pq($domElement)->text() == $clubname) ? $domElement : null;
        });
        

        编辑 2

        这是demo of the jQuery version

        如果 phpQuery 执行它在其 documentation 中所说的那样,那么(从 javascript 正确翻译)它应该以相同的方式匹配所需的元素。

        编辑 3

        在阅读了更多关于phpQuery callback system 的内容后,以下代码更有可能运行:

        function textFilter($i, $el, $text) {
            return (pq($el)->text() == $text) ? $el : null;
        }};
        $match = $dom->find("td")->map('textFilter', new CallbackParam, new CallbackParam, $clubname);
        

        请注意,-&gt;map() 优于 -&gt;filter(),因为 -&gt;map() 支持更简单的方法来定义参数“位置”(请参阅​​参考页面中的示例 2)。

        【讨论】:

        • Gijsve,文档表明我的代码应该可以工作,但我没有办法测试这些东西。你试过了吗,如果是,结果如何?
        • 地图实际上是一个不同于过滤器的概念。 filter 减少返回值,map 只是重写它。
        • 这不太正确@pguardiario。 .map() 肯定与 .filter() 不同,但与您描述的不同。正如.map() 的 jQuery 文档所说,“通过一个函数传递当前匹配集中的每个元素,生成一个包含返回值的新 jQuery 对象”。因此.map() 是一个非常灵活的设备,它返回一个jQuery 包装的数组,其中包含其回调返回的任何内容。通过选择性地返回原始 jQuery 对象的 DOM 元素,.map() 的行为与.filter() 非常相似,但能够应用非常具体的过滤规则,如上所述。
        • 过滤器可以做同样的事情。当您应该使用过滤器时,您正在使用 map,因此,您的结果中会出现一堆不必要的空值。换句话说,当你需要转换元素(将它们映射到其他东西)时使用 map,当你试图减少(过滤)结果集时使用 filter。
        • @Gijsve,请参阅我的编辑 3。请尝试一下。我想知道它是否有效。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-04
        • 2014-05-08
        • 1970-01-01
        • 2018-10-24
        • 2011-12-19
        • 1970-01-01
        相关资源
        最近更新 更多