Ich wusste bisher nicht, dass man ISBN-Nummern validieren kann. Das macht die Suche in Texten erstaunlich einfach.

Da ich gerade an einer PHP-Bibliothek zur Extraktion von Informationen aus Texten arbeite, hier mal ein kleiner Ausschnitt, nämlich der Teil, mit dem man ISBN-Nummern aus Dateien ziehen kann.

Aufbau von ISBN-Nummern

Zuerst einmal müssen wir uns aber klarmachen, wie ISBN-Nummern aussehen und aufgebaut sind. Es gibt grundsätzlich zwei Typen, ISBN-10 und ISBN-13 mit 10 respektive 13 Ziffern. Dabei können Bindestriche zwischen den einzelnen Gruppen von Ziffern stehen. Beide Typen werden unterschiedlich validiert.

Validierung von ISBN-10

Für ISBN-10 sieht die Formel zur Validierung so aus ( bezeichnet die i-te Ziffer der ISBN-Nummer):

Nun mag man sich wundern, warum Modulo 11, da dann auch 10 herauskommen kann. Das ist richtig, aber 10 wird dann zu X umgewandelt, sodass eine ISBN-Nummer mit Prüfziffer 10 ein X am Ende stehen hat.

Dabei ist die 10. Ziffer der Nummer die Prüfziffer.

Validierung von ISBN-13

Die Formel für ISBN-13 sieht etwas komplizierter aus ( bezeichnet erneut die i-te Ziffer der ISBN-Nummer):

Dabei ist die 13. Ziffer der Nummer die Prüfziffer.

Validierung in Code

Wollen wir uns also ansehen, wie die Validierung in PHP-Code aussehen kann. Der Code stammt aus meinem Ansatz zur Extrahierung von ISBN-Nummern in meiner Bibliothek. Deshalb sind hier Klassenmethoden gegeben.

<?php
private function validate($isbn) {
  $isbn = preg_replace('/[^\d]+/', '', $isbn);
  
  if (strlen($isbn) == 10) {
     return $this->validate10($isbn);
  } elseif (strlen($isbn) == 13) {
     return $this->validate13($isbn);
  } else {
     return false;
  }
}

private function validate10($isbn) {
  $sum = 0;
  
  for ($i = 1; $i <= 9; $i++) {
     $digit = (int) $isbn[$i-1];
     $sum += $i * $digit;
  }
  
  $checkDigit = $sum % 11;
  
  if ($checkDigit == 10) {
     $checkDigit = 'X';
  }
  
  if ($isbn[9] == $checkDigit) {
     return true;
  } else {
     return false;
  }
}

private function validate13($isbn) {
  $sum = 0;
  
  for ($i = 1; $i <= 12; $i++) {
     $digit = (int) $isbn[$i-1];
     $sum += $digit * pow(3, ($i+1) % 2);
  }
  
  $checkDigit = (10 - ($sum % 10)) % 10;
  
  if ($isbn[12] == $checkDigit) {
     return true;
  } else {
     return false;
  }
}

Das ist eigentlich auch schon der wichtigste Teil zum Finden von ISBN-Nummern. Anstatt eines komplizierten Regulären Ausdrucks können wir nun einfach alles heraussuchen, was wie eine ISBN-Nummer aussieht und es auf die Korrektheit der Prüfziffer und die korrekte Länge prüfen.

Bei mir läuft das im Moment so ab:

  1. einen Whitespace-Tokenizer über den Text laufen lassen, sodass man alle mit Leerzeichen und Ähnlichem abgetrennten Zeichen hat
  2. jeden einzelnen Token darauf prüfen, ob er nur Ziffern, Bindestriche und X (wichtig!) enthält
  3. die verdächtigen Ergebnisse anhand der Ziffernlänge (ohne Bindestriche) und eventuell auch noch der Prüfsumme validieren

Schon hat man ISBN-Nummern gefunden.