1

My HTML table:

$table = <<< EOD
<table>
    <tbody>
        <tr style="border:none;">
            <td>1</td>
            <td>[[name_21]]</td>
            <td>[[charge_2]]</td>
        </tr>
        <tr style="border:1px solid #aaa;">
            <td>2</td>
            <td>[[name_13]]</td>
            <td>[[charge_5]]</td>
        </tr>
        <tr style="border:1px solid #ccc;">
            <td>3</td>
            <td>[[name_24]]</td>
            <td>[[charge_13]]</td>
        </tr>
        <tr style="border:1px solid #555;">
            <td>4</td>
            <td>[[name_22]]</td>
            <td>[[charge_22]]</td>
        </tr>
    </tbody>
</table>
EOD;

This is how I get all charge_X values.

preg_match_all('/\[\[charge_(\d+)\]\]/', $table, $charge_ids);

Remove table row that has charge_13 in its cell.

if (isset($charge_ids)) {
    if (array_key_exists('1', $charge_ids)) {
        $charge_ids = $charge_ids[1];
        $table_replaced = $table;

        foreach ($charge_ids as $charge_id) {
            if ($charge_id == '13') {
                // this line is removing table row if condition met in table cell.
                $table_replaced = preg_replace('/<tr[^>]*>(\[\[charge_'.$charge_id.'\]\])<\/tr>/iUums', 'a', $table_replaced);
            }
        }

        echo $table_replaced;
    }
}

This code still doesn't work. How to remove table row if table cell has charge_13 in it?

  • In td may contain just charge_X or charge_X with text. for example: <td>[[charge_13]] USD</td>
  • The charge_X value may contain in different order of table cell. for example: <tr><td>3</td><td>[[charge_13]]</td><td>[[name_24]]</td></tr>
  • There may be unicode text in table cell, such as Chinese or Thai characters.
  • preg_replace or DOMDocument are welcome.
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
vee
  • 4,506
  • 5
  • 44
  • 81
  • Please _never_ use regexps to parse HTML. Use e.g. [`SimpleXML`](http://php.net/manual/en/book.simplexml.php) or family. – Aleksei Matiushkin Feb 09 '15 at 09:40
  • What on earth are you doing? If you work in PHP simply don't put the row in the table in the first place. Don't ever try to do this, please. If it is a template, make it easy for yourself to do this kind thing. – KIKO Software Feb 09 '15 at 09:41
  • @KIKOSoftware It's data table. If you don't use table then what will you use? – vee Feb 09 '15 at 09:44
  • @vee: You should add in a `[[display13]]` like this: `` and then replace this with `display:none` if you don't want to row to be visible, and with nothing when it should show. You're not supposed to change the template itself. But hey, I would never do it like this. If you have a variable table, I would generate the table in PHP, so the problem never occurs. – KIKO Software Feb 09 '15 at 09:54
  • @KIKOSoftware Thank you. And yes, i agree with you that table should be in PHP but this is the option i offer to my user that they can design their own template. However, thanks again. I'm trying on Dom document if that can be solve the problem. – vee Feb 09 '15 at 10:01
  • Possible duplicate of [Using regular expressions to parse HTML: why not?](https://stackoverflow.com/questions/590747/using-regular-expressions-to-parse-html-why-not) – Brian Tompsett - 汤莱恩 Nov 05 '17 at 18:12

1 Answers1

1

Use DOMDocument.

$table = <<< EOD
<table>
    <tbody>
        <tr style="border:none;">
            <td>1</td>
            <td>[[name_21]]</td>
            <td>[[charge_2]]</td>
        </tr>
        <tr style="border:1px solid #aaa;">
            <td>2</td>
            <td>[[name_13]]</td>
            <td>[[charge_5]]</td>
        </tr>
        <tr style="border:1px solid #ccc;">
            <td>3</td>
            <td>[[name_24]]</td>
            <td>[[charge_13]]</td>
        </tr>
        <tr style="border:1px solid #555;">
            <td>4</td>
            <td>[[name_22]]</td>
            <td>[[charge_22]]</td>
        </tr>
    </tbody>
</table>
EOD;

$dom = new \DOMDocument();
$dom->loadHTML($table);
$xpath = new \DOMXPath($dom);

// loop all <tr> element.
foreach ($xpath->query('//tr') as $tr) {
    $tds = $tr->getElementsByTagName('td');
    // get total <td> in this <tr>
    $total_item = $tds->length;

    // loop to all <td> and check.
    for ($i = 0; $i <= ($total_item-1); $i++) {
        // get table cell value.
        $table_cell_value = $tds->item($i)->nodeValue;
        preg_match('/\[\[charge_(\d+)\]\]/', $table_cell_value, $charge_id);

        // check if condition is met, the charge_id is 13.
        if (is_array($charge_id) && array_key_exists(1, $charge_id) && $charge_id[1] == 13) {
            // condition met. charge_id is 13. remove this table row.
            $tr->parentNode->removeChild($tr);
        }
        unset($charge_id, $table_cell_value);
    }

    unset($tds, $total_item);
}

// get the result
$saved_html = preg_replace('~<(?:!DOCTYPE|/?(?:html|body))[^>]*>\s*~i', '', $dom->saveHTML());
echo $saved_html;
vee
  • 4,506
  • 5
  • 44
  • 81