user3813111
user3813111

Reputation: 11

error in php code using preg_match_all

hello i done a code i need some help :) it keep give me nothing , no result

ok here the code

<?php
$f='        <tr class="hover">

            <td class="ra " >3.</td>
            <td class="pla " ><a href="spieler.php?uid=3010">الـعـاصـفـة</a> </td>
            <td class="al " ><a href="allianz.php?aid=127">|BRAVE|</a></td>
            <td class="pop " >2519</td>
            <td class="vil " >6</td>
        </tr>

        <tr class="hover">

            <td class="ra " >3.</td>
            <td class="pla " ><a href="spieler.php?uid=4292">LOOK</a> </td>
            <td class="al " ><a href="allianz.php?aid=127">|BRAVE|</a></td>
            <td class="pop " >2001</td>
            <td class="vil " >5</td>
        </tr>

        <tr class="hover">

            <td class="ra " >4.</td>
            <td class="pla " ><a href="spieler.php?uid=2784">بو سعود</a> </td>
            <td class="al " ><a href="allianz.php?aid=127">|BRAVE|</a></td>
            <td class="pop " >1966</td>
            <td class="vil " >5</td>
        </tr>';
preg_match_all ("/<td class=\"pla \" ><a href=\"spieler.php?uid=(.*)\">(.*)<\/a> <\/td>/", $f, $result , PREG_SET_ORDER);
// putting data to array
foreach($result as $item){
   $player=$item[2];
   $text = "$player
";
print $text;
}



?>

Can some one tell me what is the wrong ? and show mw how to fix it ? thanks alot

Upvotes: 1

Views: 68

Answers (2)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

If I'm not wrong @vch and @DirkPitt have already solve a part of your problem.

As an aside, to avoid errors and make your code more readable, you should follow these good practices:

  • when you have a long pattern, use the free-spacing/verbose/comment/extended/... mode. You can switch it on with the x modifier. With this mode, all whitespaces are ignored and inline comments are allowed (after a #). To write a literal space you must put it in a character class or between \Q and \E
  • when you have a pattern that is full of double quotes, use single quotes and vice versa. If your pattern is full of both, use the nowdoc syntax.
  • in the same idea, the slash is not mandatory as delimiter, you can use the tilde or an other character (avoid to use a regex special character even if it is allowed)
  • when you have, in the pattern, a literal substring that may contain regex special characters (like . or ?). Instead of escaping all these characters, you can put the substring between \Q and \E.
  • you can give a name to your capture groups. It's more readable to use something like $m['txt'] instead of $m[1]. you don't need to remember the index.

Example:

$pattern = '~
    \Q<td class="pla " >\E         # these parts are seen as literal strings
    \Q<a href="spieler.php?uid=\E  # whitespaces outside \Q...\E are ignored
    (?<id>  [^"]* ) ">             # named capture id 
    (?<txt> .*? )
    \Q</a> </td>\E ~x';

if (preg_match_all($pattern, $str, $m, PREG_SET_ORDER)) {
    foreach ($m as $v) {
        echo "\nid: " . $v['id'] . "\ttxt: " . $v['txt'];
    }
}

It isn't usually a good idea to parse html with regex because the html language have a very flexible syntax that can hide many traps. For example, if I add a single space here:<td class=" pla " > the pattern will fail. But in your example it is not the case, since all the table seems to have the same structure, whitespaces and indentation.

Here is a more recommended way to do it without regex:

$xpath = new DOMXPath(DOMDocument::loadHTML('<?xml encoding="UTF-8">' . $str));
$linkNodes = $xpath->query('//tr[contains(@class, "hover")]'
                         . '/td[contains(@class, "pla")]/a');

foreach ($linkNodes as $node) {
    echo "\nid: " . explode('=', $node->getAttribute('href'))[1]
       . "\ttxt: " . $node->textContent;
}

Instead of dealing with a string, you are dealing with the DOM tree using paths and attributes to get the target nodes (the 'a' tags). Once you get them, you only need to loop on the nodeList and use the method getAttribute() and the property textContent to obtain what you want.

Upvotes: 1

Wojciech S.
Wojciech S.

Reputation: 16

Try to use lazy regular expression:

Replace this:

(.*)

With this:

(.*?)

Also escape special signs like . and ?

Upvotes: 0

Related Questions