HTML Tabellen filtern mit preg_match_all

Descartes

Erfahrenes Mitglied
Hallo!

Ich versuche gerade einen HTML Quelltext darauf zu überprüfen, ob mindestens zwei Dezimalzahlen oder zwei Brüche in der Form xx.xx bzw. xx/xx darin vorkommen.

Mein Problem Nr.1: Es sollen nur Zahlen der Form xx.xx, x.xx, xx.x, x.x im Ergebnis auftauchen, nicht aber xxx.x oder x.xxx etc., also nur je zwei Stellen vor oder nach dem . bzw. /.

Mein Problem Nr.2: Der Quelltext enthält teils verschachtelte Tabellen, und ich will nur diejenigen herausfiltern, die eine Zahl (xx.xx od. xx/xx - siehe Frage1) enthalten.

Etwa:

<table>
<tr>
<td>Irgendwas</td>
<td>
<table>
<tr>
<td>xyz</td>
<td>xx.xx</td>
</tr>
</table>
</td>
<td>Irgendwas</td>
</tr>
</table>

und ich will nur das haben:

<table>
<tr>
<td>xyz</td>
<td>xx.xx</td>
</tr>
</table>

Hier ist das was ich bisher habe, aber dabei werden auch Zahlen der Form x.xxx im Ergebnis als x.xx (die ja in x.xxx enthalten ist) berücksichtigt.

Code:
// Einlesen der zu untersuchenden Datei
$content =  file_get_contents($file);
  
  // Umwandeln des Inhalts in Kleinbuchstaben
	$content = strtolower($content);
	// Umwandeln aller HTML Sonderzeichen in ASCII
	$content = html_entity_decode($content);
         // Entfernen aller JavaScript Bereiche
         $content = preg_replace("'<script[^>]*?>.*?</script>'si", "", $content);
         // Entfernen aller PHP und HTML Tags außer <(/)table>, <(/)tr>, <(/)td>
	$content = strip_tags($content, "<table></table><tr></tr><td></td>");      
         // Entfernen der Variablen in HTML Tags
                 //Suche <table ...> und überschreibe mit <table>
                 $content = preg_replace("'<table[^>]*?>'", "<table>", $content);
                 //Suche <tr ...> und überschreibe mit <tr>
                 $content = preg_replace("'<tr[^>]*?>'", "<tr>", $content);
                 //Suche <td ...> und überschreibe mit <td>
                 $content = preg_replace("'<td[^>]*?>'", "<td>", $content);               

  // Prüfung auf mindestens zwei Zahlen in der Form xx.xx oder xx/xx
  preg_match_all("'\d{1,2}(\.|/)\d{1,2}'", $content, $treffer);
  
  $treffer2 = count($treffer[0]);
  echo $treffer2."<br>";

  for ($i=0; $i< count($treffer[0]); $i++) {
  echo "Treffer 1: ".$treffer[0][$i]."<br>";
  echo "Treffer 2: ".$treffer[1][$i]."<br>";
  }
  
  // Reduzieren des Inhalts auf Tabellen die xx.xx|xx/xx enthalten 
  preg_match_all("'<table>(.*)(\d{1,2}(\.|/)\d{1,2})(.*)</table>'", $content, $treffer);

  $treffer2 = count($treffer[0]);
  echo $treffer2."<br>";

  for ($i=0; $i< count($treffer[0]); $i++) {
  echo "Treffer 1: ".$treffer[0][$i]."<br>";
  echo "Treffer 2: ".$treffer[1][$i]."<br>";
  }

// Ausgabe des Ergebnisses
echo $content;

Leider arbeite ich zum Ersten mal mit den preg_... - Funktionen und durch herumprobieren bin ich einfach nicht weitergekommen ...

Vielen Dank für Eure Tips und/oder Hilfen!

Grüße

Martin
 
Es geht auch einfacher:
PHP:
<?php

	if( preg_match_all('/[0-9]+(?:\x2E|\x2F)[0-9]+/', $string, $matches) ) {
		$matches = $matches[0];
		echo '<pre>';
		print_r($matches);
		echo '</pre>';
	}

?>
 
Ich persoenlich finde die Ausgabe von print_r nicht so berauschen und nutze dafuer lieber folgenden Code:

PHP:
printf(nl2br(print_r($matches,true)));
Ich find's einfach uebersichtlicher jeden Wert des Arrays in einer neuen Zeile zu haben.
 
Hallo!

Ersteinmal Danke für Eure Tipps.

Habe jetzt meinen Code auf
Code:
// Prüfung auf mindestens zwei Zahlen in der Form xx.xx oder xx/xx
  if (preg_match_all('/([0-9]+(?:\x2E|\x2F)[0-9]+)/', $content, $matches)) { 
        
        $matches = $matches[0]; 
        echo '<pre>'; 
        printf(nl2br(print_r($matches,true))); 
        echo '</pre>'; 
   }

geändert.

Mein Problem besteht aber weiterhin, denn Werte die drei- oder mehrstellig vor oder hinter dem Punkt sind, werden im Ergebnis berücksichtigt.

Habe es in einer zweiten if Abfrage mit

Code:
// Prüfung auf mindestens zwei Zahlen in der Form xx.xx oder xx/xx
  if(preg_match_all('/([0-9]+(?:\x2E|\x2F)[0-9]+)/', $content, $matches)) { 
        
        if (!preg_match_all('/([0-9]{3,}(?:\x2E|\x2F)[0-9]{3,})/', $content, $matches)){
        
        $matches = $matches[0]; 
        echo '<pre>'; 
        printf(nl2br(print_r($matches,true))); 
        echo '</pre>'; 
        }
    }

versucht, dann bleibt das Ergebnis aber leer.
Die Klammer {3,} bedeutet doch, dass mindestens drei Ziffern von 0-9 vorhanden sein müssen und mit "!" vor preg_match_all negiere ich das dann. Folglich kommt das Skript nicht in die innerste Schleife, wenn mehr als drei Ziffern vor oder nach dem . bzw. / vorhanden sind.

Funktioniert aber nicht :confused:

Grüße

Martin
 
Probier mal Folgendes:
PHP:
<?php

	if( preg_match_all('/[^0-9][0-9]{1,2}(?:x2E|\x2F)[0-9]{1,2}/', $string, $matches) ) {
		$matches = $matches[0];
		echo '<pre>';
		print_r($matches);
		echo '</pre>';
	}

?>
 
Hallo!

Originalwerte:

1.70
444.00
35.555
01/800
1.65


Das [^0-9] bewirkt, dass im Ergebnis das letzte Zeichen (>) vor der Zahl mit im Ergebnis ausgegeben wird und die 444.00 wird geschluckt, da erstes Zeichen nicht aus [0-9]

[11] => >1.70
[12] => >35.55
[13] => >01/80
[14] => >1.65

Wenn ich den Ausdruck in
Code:
preg_match_all('/[^0-9][0-9]{1,2}(?:\x2E|\x2F)[0-9]{1,2}[^0-9]/', $content, $matches)
abändere, dann wird das Ergebnis schon ziemlich gut. Alle Werte die raus müssen sind raus, allerdings wird das Ergebnis von dem Zeichen davor und danach "eingerahmt".

[11] => >1.70<
[12] => >1.65<

Trotzdem schon mal vielen Dank!

Martin
 
Hallo!

Frage 1 gelöst!

Code:
preg_match_all('/(?<![0-9])\d{1,2}(?:\x2E|\x2F)\d{1,2}(?![0-9])/', $content, $matches)

Und das Zauberwort heißt "Assertions".

Jedem der mit Regular Expressions zu kämpfen hat, kann ich dieses kleine Helferlein empfehlen:

http://weitz.de/regex-coach

Grüße

Martin
 
Zurück