praetor: Aufzählungen von Begriffen

Ich will mit einem Perlskript eine XML-Datei bearbeiten, und zwar handelt es sich um Gesetzestexte wo ich bei jedem Verweis auf einen anderen Paragraphen einen link einfügen will. Probleme bereiten mir dabei ganze Aufzählungen von Paragraphen. Sie werden durch '§§' eingeleitet und mittels Komma, 'oder', 'und' oder 'bis' aneinandergereiht. Bisher habe ich mir für jede Kombination einen regulären Ausdrück definiert, aber die Anzahl der möglichen Kombinationen gehen in's unendliche. Es muß eine abstraktere Lösung geben.

Bisher hab ich's so gelöst (Beispiel, etwas vereinfacht):

§§ [n] und [n]

$_ =~ s/§§ ([0-9]+) und ([0-9]+)/§§ <link url="\1.html">\1</link> und <link url="\2.html">\2</link> /g

aber bei Aufzählungen wie
#§§ [n], [n] bis [n], [n] bis [n] oder [n] und [n]
bin ich ob der Zweckmäßigkeit meiner Lösung in's Grübeln gekommen. Könnte mir einer einen Hinsweis geben, wie ich einen besseren Lösungsweg finden kann?

  1. Halihallo

    Bisher hab ich's so gelöst (Beispiel, etwas vereinfacht):

    §§ [n] und [n]

    $_ =~ s/§§ ([0-9]+) und ([0-9]+)/§§ <link url="\1.html">\1</link> und <link url="\2.html">\2</link> /g

    aber bei Aufzählungen wie
    #§§ [n], [n] bis [n], [n] bis [n] oder [n] und [n]

    "[n]" und "[n] bis [n]" ist klar definiert, aber was meinst du mit
    "[n] bis [n] oder [n] und [n]"? - Die Verknüpfung der Operatoren ist hier nicht eindeutig. Da müsstest du wahrscheinlich mit Klammerebenen arbeiten. Erzähl noch etwas, was du mit 'bis', 'oder' und 'und' genau meinst und was die für Konsequenzen haben.

    bin ich ob der Zweckmäßigkeit meiner Lösung in's Grübeln gekommen. Könnte mir einer einen Hinsweis geben, wie ich einen besseren Lösungsweg finden kann?

    Eine einfache Liste:

    §§ 1, 3, 5, 10-20, 33

    Was wäre hier falsch? - bzw. was würde damit nicht unterstützt werden?

    Viele Grüsse

    Philipp

    1. Herzlichen Dank zunächst für die Antwort

      Eine einfache Liste:

      §§ 1, 3, 5, 10-20, 33

      Was wäre hier falsch? - bzw. was würde damit nicht unterstützt werden?

      Na ja, der Gesetzestext ist ja vorgegeben. Da kommen die unmöglichsten Aufzählungen vor. Ein abschreckendes Beispiel ist § 100c StPO. Die bisherige Lösung stößt auch an weitere Grenzen. Wenn die Aufzählung mehr als 9 Paragraphen enthält, funktioniert die Wiedergabe der Klammerung nicht mehr (ab '\10'). Außerdem gibt es auch Verweise auf andere Gesetze. Ich würde mir eine Lösung ungefähr nach folgender Logik vorstellen.

      • Wenn eine Aufzählung durch '§§' eingeleitet wird, finde das Aufzählungsende (= Satzendepunkt oder Gesetzesangabe).
      • Stelle dabei fest, ob auf ein anderes Gesetz verwiesen wird, wenn ja, auf welches (Eine Liste der Gesetze mit den entsprechenden Kürzeln ist in dem Skript bereits definiert).
      • identifiziete die Paragraphenangaben (= [0-9a-z]+ nach "Bindeglied"; mögliche Bindeglieder sind ', ', ' und ', ' oder ', ' bis ', ' in Verbindung mit ')
      • verlinke jede dieser Angaben
          - externe Verweise: 'url="../[Gesetz]/[Gesetz][§].html"'
          - interne Verweise: 'url="[Gesetz][§].html"'

      Ich hoffe, daß diese Angaben einigermaßen verständlich sind. Jedenfalls reichen meine Perlkenntnisse und mein Programmiergeschick für so etwas nicht mehr aus. Beste Grüße und herzlichen Dank im Voraus.

      Georg

      1. Halihallo <!-- In diesem Forum wird man gerne begrüsst

        Eine einfache Liste:

        §§ 1, 3, 5, 10-20, 33

        Was wäre hier falsch? - bzw. was würde damit nicht unterstützt werden?

        Na ja, der Gesetzestext ist ja vorgegeben. Da kommen die unmöglichsten Aufzählungen vor. Ein abschreckendes Beispiel ist § 100c StPO. Die bisherige Lösung stößt auch an weitere Grenzen. Wenn die Aufzählung mehr als 9 Paragraphen enthält, funktioniert die Wiedergabe der Klammerung nicht mehr (ab '\10').

        Was meinst du mit Klammerung?

        [...]

        mal schaun, was wir da machen können...

        also, wir haben doch etwa folgendes:

        §§ [n], [n] bis [n], [n] bis [n] oder [n] und [n]

        also, alles was [n] ist, sind Paragraphen, die "URL-kodiert" werden sollen (gelinkt werden); alles andere soll so bleiben wie's war. Dann könnte ich mir folgendes vorstellen:

        my @codes = split(/, /, $reference_line);
           # @reference_line ist die genannte §§... linie
           # @codes sind dann z. B. '[n]' oder '[n] und [n]'

        my @struct;

        einlesen und codieren...

        foreach my $code (@codes) {
           if ($code =~ /[1]+$/) {
              push @struct, ['simple_paragraph', $code];
              next;
           }
           my @to_parse = split( / /, $code );
              # @to_parse = ('[n]','bis','[n]','oder','[n]','und','[n]');
           foreach my $sub_code (@to_parse) {
              if ($sub_code =~ /[2]+$/) {   # also ein [n]
                 push @struct, ['simple_paragraph', $sub_code];
              } else {
                 push @struct, ['output_as_text', $sub_code];
              }
           }
        }

        und jetzt alles ausgeben...

        my $output;
        foreach (@struct) {
           if ($_->[0] eq 'simple_paragraph') {
              # $_->[1] ist nun irgendein [n], das kann hier noch
              # weiter bearbeitet werden, eg. Gesetzesbuch auslesen...
              $output .= '<a href="...">§$_->[1]</a>';
           } else {
              $output .= $_->[1];
           }
        }

        1. Hast du noch einige Beispiele (mir ist noch immer nicht ganz klar, wie die Datenstruktur aufgebaut ist; z. B. wie werden Gesetzesbücher mit den Paragraphen in Verbindung gesetzt)?
        2. Wo genau hast du Probleme?
        3. Was können wir tun, um dir bei deinem Problem zu helfen?

        Viele Grüsse

        Philipp


        1. 0-9 ↩︎

        2. 0-9 ↩︎

        1. Hallo Phillip,
          hallo Ihr alle andern,

          1. Hast du noch einige Beispiele (mir ist noch immer nicht ganz klar, wie die Datenstruktur aufgebaut ist; z. B. wie werden Gesetzesbücher mit den Paragraphen in Verbindung gesetzt)?

          Also mir schwebt folgendes Web-Projekt vor: Ich habe ein Verzeichnis für Gesetze (/leges). Für jedes einzelne Gesetz gibt es ein Unterverzeichnis, das den Namen des Gesetzeskürzels trägt, also z.B.
          '/leges/StPO' für die Strafprozeßordnung
          '/leges/BGB' für das Bürgerliche Gesetzbuch
          usw. Die Kürzel für die Gesetze sind standardisiert und eindeutig. Innerhalb hat dieser Verzeichnisse gibt es für jeden Paragraphen  des Gesetzes eine html-Datei, die den Namen des Gesetzes und die Nummer des Paragraphen trägt. Somit hat jeder Paragraph eine eindeutige URL, also z. B. § 30 BGB hat die URL
          'www.praetor/leges/BGB/BGB30.html'

          Jetzt will ich ein neues Gesetz erfassen. Es liegt mir zunächst als txt-Datei vor, die ich mittels eines Skriptes in eine XML-Datei umgewandelt habe. Der Gesetzestext enthält Verweise auf bestimmte Paragraphen im selben Gesetz und auf Paragraphen anderer Gesetze. Ein Beispiel füge ich am Ende an. Dabei will ich zu jedem angeführten Paragraphen ein Attribut 'link url="..."' definieren. Ein Verweis auf § 10 des - sagen wir des Signaturgesetzes - steht im Text als
          '... gemäß § 10 des Signaturgesetzes ...'
          Das ersetze ich durch
          '... gemäß <link url="../SigG/SigG10.html>§ 10</link> des Signaturgesetzes ...'
          Damit habe ich zunächst keine Probleme. Die kommen erst bei Aufzählungen wie z. B.
          '... sind §§ 10 bis 12 des Signaturgesetzes anzuwenden ...'
          Das heißt dann bei mir:
          '... sind <link url="../SigG/SigG10.html>§§ 10</link> bis <link url="../SigG/SigG11.html>§ 11</link> des Signaturgesetzes ...'

          Diese Aufzählungen können, wie gesagt, sehr lang und umständlich sein (siehe Beispiel). Und ich habe Probleme, daß mit meiner bisher verwendeten Syntax zu erschlagen. Ja, am Ende soll die XML-Datei natürlich mittels eines ebenfalls bereits vorhandenen Skriptes in HTML umgewandelt. Ein noch unvollendetes Beispiel läßt sich unter www.praetor.de bestaunen (oder belächeln, je nach dem ...)

          1. Was können wir tun, um dir bei deinem Problem zu helfen?

          Das gegebene Codebeispiel war schon genau richtig. Das werde ich jetzt erstmal durchackern :-).

          So long
          Georg

          Beispiel:

          aus
          § 100c der Strafprozeßordnung

          (1) Ohne Wissen des Betroffenen

          dürfen
          Lichtbilder und Bildaufzeichnungen hergestellt werden,
          sonstige besondere für Observationszwecke bestimmte technische Mittel zur Erforschung des Sachverhalts oder zur Ermittlung des Aufenthaltsortes des Täters verwendet werden, wenn Gegenstand der Untersuchung eine Straftat von erheblicher Bedeutung ist, und wenn die Erforschung des Sachverhalts oder die Ermittlung des Aufenthaltsortes des Täters auf andere Weise weniger erfolgversprechend oder erschwert wäre,
          darf das nichtöffentlich gesprochene Wort mit technischen Mitteln abgehört und aufgezeichnet werden, wenn bestimmte Tatsachen den Verdacht begründen, daß jemand eine in § 100a bezeichnete Straftat begangen hat, und die Erforschung des Sachverhalts oder die Ermittlung des Aufenthaltsortes des Täters auf andere Weise aussichtslos oder wesentlich erschwert wäre,
          darf das in einer Wohnung nichtöffentlich gesprochene Wort des Beschuldigten mit technischen Mitteln abgehört und aufgezeichnet werden, wenn bestimmte Tatsachen den Verdacht begründen, daß jemand
          eine Geldfälschung, eine Wertpapierfälschung (§§ 146, 151, 152) oder eine Fälschung von Zahlungskarten und Vordrucken für Euroschecks (§ 152a des Strafgesetzbuches), einen schweren Menschenhandel nach § 181 Abs. 1 Nr. 2, 3 des Strafgesetzbuches, einen Mord, einen Totschlag (§§ 211, 212 des Strafgesetzbuches) oder einen Völkermord (§ 6 des Völkerstrafgesetzbuches), eine Straftat gegen die persönliche Freiheit (§§ 234, 234a, 239a, 239b des Strafgesetzbuches), einen Bandendiebstahl (§ 244 Abs. 1 Nr. 2 des Strafgesetzbuches) oder einen schweren Bandendiebstahl (§ 244a des Strafgesetzbuches), einen schweren Raub (§ 250 Abs. 1 oder Abs. 2 des Strafgesetzbuches), einen Raub mit Todesfolge (§ 251 des Strafgesetzbuches) oder eine räuberische Erpressung (§ 255 des Strafgesetzbuches), eine Erpressung (§ 253 des Strafgesetzbuches) unter den in § 253 Abs. 4 Satz 2 des Strafgesetzbuches genannten Voraussetzungen, eine gewerbsmäßige Hehlerei, eine Bandenhehlerei (§ 260 des Strafgesetzbuches) oder eine gewerbsmäßige Bandenhehlerei (§ 260a des Strafgesetzbuches), eine Geldwäsche, eine Verschleierung unrechtmäßig erlangter Vermögenswerte nach § 261 Abs. 1 bis 4 des Strafgesetzbuches, eine Bestechlichkeit (§ 332 des Strafgesetzbuches) oder eine Bestechung (§ 334 des Strafgesetzbuches),
          eine Straftat nach § 52a Abs. 1 bis 3, § 53 Abs. 1 Satz 1 Nr. 1, 2, Satz 2 des Waffengesetzes, § 34 Abs. 1 bis 6 des Außenwirtschaftsgesetzes oder nach § 19 Abs. 1 bis 3, § 20 Abs. 1 oder 2, jeweils auch in Verbindung mit § 21, oder § 22a Abs. 1 bis 3 des Gesetzes über die Kontrolle von Kriegswaffen,
          eine Straftat nach einer in § 29 Abs. 3 Satz 2 Nr. 1 des Betäubungsmittelgesetzes in Bezug genommenen Vorschrift unter den dort genannten Voraussetzungen oder eine Straftat nach §§ 29a, 30 Abs. 1 Nr. 1, 2, 4, § 30a oder § 30b des Betäubungsmittelgesetzes,
          Straftaten des Friedensverrats, des Hochverrats und der Gefährdung des demokratischen Rechtsstaates oder des Landesverrats und der Gefährdung der äußeren Sicherheit (§§ 80 bis 82, 85, 87, 88, 94 bis 96, auch in Verbindung mit § 97b, §§ 97a, 98 bis 100a des Strafgesetzbuches),
          eine Straftat nach § 129 Abs. 4 in Verbindung mit Abs. 1, § 129a des Strafgesetzbuches oder
          eine Straftat nach § 92a Abs. 2 oder § 92b des Ausländergesetzes oder nach § 84 Abs. 3 oder § 84a des Asylverfahrensgesetzes begangen hat und die Erforschung des Sachverhalts oder die Ermittlung des Aufenthaltsortes des Täters auf andere Weise unverhältnismäßig erschwert oder aussichtslos wäre.

          1. Halihallo praetor

            1. Hast du noch einige Beispiele (mir ist noch immer nicht ganz klar, wie die Datenstruktur aufgebaut ist; z. B. wie werden Gesetzesbücher mit den Paragraphen in Verbindung gesetzt)?

            Diese Aufzählungen können, wie gesagt, sehr lang und umständlich sein (siehe Beispiel). Und ich habe Probleme, daß mit meiner bisher verwendeten Syntax zu erschlagen. Ja, am Ende soll die XML-Datei natürlich mittels eines ebenfalls bereits vorhandenen Skriptes in HTML umgewandelt. Ein noch unvollendetes Beispiel läßt sich unter www.praetor.de bestaunen (oder belächeln, je nach dem ...)

            Ich finde dein Projekt sehr interessant! - Nur immer weiter...

            Hm. Der Datentype für den Input ist ja alles andere, als Computerfreundlich... Warum können die vom W3C nicht mal eine Mensch-Computer-Sprache entwickeln, die sich gleichermassen von Menschen, wie auch vom Computer lesen lassen? :-)

            <snip>
            eine Wertpapierfälschung (§§ 146, 151, 152) oder eine Fälschung von Zahlungskarten und Vordrucken für Euroschecks (§ 152a des Strafgesetzbuches),
            </snip>

            Hm. Hier stellt sich mir auch noch die Frage, wie diese "relevanten" Teststellen überhaupt aus dem Input-Stream ausgefiltert werden können. Hast du hierbei schon etwas gemacht?
            Und soll "§ 152a des Strafgesetzbuches" etwa transformiert werden, eg. in "§§ 152a StGB" oder so, dass es nachher weitertransformiert werden kann, sodass ein Link in die XML geschrieben wird?
            Ich denke, dass du keinen manuellen Aufwand betreiben willst, oder?

            Hast du eine allgemeine Definition von "Ende der Paragraphenaufzählung" gefunden? - Der Anfang wird ja mit '§§' gebildet.

            Allgemein musst du hier wohl ein rekursives Verfahren anwenden, dass

            1. den Text einliest
            2. Paragraphendefinitionen aus dem Input-Stream entfernt, bzw. bearbeitet
            3. Paragraphendefinitionen analysiert/parsed
            4. und diese dann als <link> in die XML schreibt bzw. wieder in den Input-Stream an der richtigen Stelle verschiebt.

            Möglichkeit zur Paragraphenextraktion:
            Nach §§ suchen. Dann den Input-Stream wort-für-wort zu testen, bis kein [n] bzw. Stoppword mehr vorkommt...

            Die Stoppwords sind hierbei etwa folgende:
            ' '
            'und'
            'oder'
            ','
            '.'
            'Strafgesetzbuch'
            'StGB'
            ...

            falls eine Zeichenkette eine Zahl ist, wird diese (da in einer Paragraphenaufzählung) in einen <link...> transformiert. Falls keines der Stoppwords auftaucht, bzw, keine auch keine Zahl zwischen Stoppwords, dann wird ein Flag "normaler-text" gesetzt, was bedeutet, dass keine Transformationen stattfinden. Die Stoppwords werden natürlich auch wieder in den Input-Stream (bzw. den Output-Stream) eingefügt.

            Vielleicht ist das ein neuer Input.

            Viele Grüsse

            Philipp

            1. Hallo Philip,

              also ich habe das Problem definitiv erschlagen, mit einer für mich etwas überraschenden Logik. Aber ich hab's ausgiebig getestet, und es funktioniert zuverlässig. Herzlichen Dank nochmal für Deinen Zuspruch.

              Georg

              Auszug:

              my $lex = "StPO";
              my $pfad = "...";
              open(ein, "<$pfad/$lex.xml");
              my @zeilen = <ein>;
              close(ein);

              my %leges = (
                 "Abgabenordnung" => AO,
                 "Artikel 10-Gesetz" => G10,
                 usw ... );

              open(aus, ">$pfad/$lex-1.xml");
              my @leges = keys(%leges);

              foreach(@zeilen){
                 $zl = $_;

              # Zeilenumbruch nach Gesetzesangabe
                 foreach(@leges){
                    $zl =~ s/($_[^< ]*)/\1\n/g;
                    }
                 print aus "$zl";
                 }
              close(aus);

              ###############################################################

              Datei neu einlesen

              open(ein, "<$pfad/$lex-1.xml");
              my @zeilen = <ein>;
              close(ein);
              open(aus, ">$pfad/$lex-1.xml");

              my $zl = "";                            # Zeileninhalt
              my @i;                                  # Input-Array
              my $ist = 0;                            # Inputstatus
              my $klex;                               # Gesetzeskürzel
              my $llex;                               # Gesetzesangabe lang

              foreach(@zeilen){
                 $zl = $_;
                 $llex = "irgendwas";
                 $klex = $lex;

              # teste alle Gesetze und ermittle $llex und $klex
                 foreach(@leges){
                    if($zl =~ "$_"){
                       $llex = $_;                    # Gesetzesbezeichung lang
                       $klex = $leges{$_};            # Gesetzeskürzel
                       }
                    }

              # erschlage Aufzählungen von Paragraohen
                 if($zl =~ "[^>]§§ "){

              @i = split(/ /, $zl);             # Zerlege die aktuelle Zeile ($zl).
                    $zl = "";                         # Lösche (alten) Zeileninhalt.
                    $sti = 0;                         # Statusschalter für Input
                    foreach(@i){
                       if($_ =~ "[(]?§§"){
                          $sti = 1;                   # Schalte Input-Status ein.
                          }
                       if($_ =~ "[A-Z].*"){
                          $sti = 0;                   # Schalte Input-Status aus (Aufzählungsende).
                          }
                       if($sti == 1){                 # Verlinke (ggf.) Paragraphenangaben)
                          # Der Linkzauber.
                          $_ =~ s/([0-9]+[a-z]*)(.*)/<link url="../$klex/$klex\1.html">\1</link>\2/;
                          }
                       }
                    $zl = join(" ", @i);              # Setze die Zeile ($zl) wieder zusammen.
                    @i = "";                          # Setze @i zurück.
                    }

              # Einfacher Paragraph
                 # Wenn ein Satzende (. [A-Z]) vor der Gesetzesangabe steht, gehört § nicht dazu.
                 $zl =~ s/([^>§])§ ([0-9a-z]+)(.*. [A-Z].*$llex)/\1§ <link url="$lex\2.html">\2</link>\3/g;
                 # Wenn die Gesetzesangabe eingeklammert isch, gehört § nicht mit dazu
                 $zl =~ s/([^>§])§ ([0-9a-z]+)(.*(§.*$llex[a-z]*))/\1§ <link url="$lex\2.html">\2</link>\3/g;
                 # ich versteh nit, wieso, aber wenn die Zeile fehlt, gibt es Fehler
                 $zl =~ s/([^>§])§ ([0-9a-z]+) (.*(§.*$llex[a-z]*))/\1§ <link url="$lex\2.html">\2</link> \3/g;
                 # Sonst ist es einfacher
                 $zl =~ s/([^>§])§ ([0-9a-z]+)/\1§ <link url="../$klex/$klex\2.html">\2</link>/g;

              # Gesetz
                 $zl =~ s/ ($llex[a-z]*)/ <link url="../$klex/$klex.html">\1</link>/;

              $zln = $zln+1;                       # Zeilennummer
                 print aus "$zl";
                 print "$zln\n";
                 }

              system("lex2html.pl");

              #####################################################################

    2. "[n]" und "[n] bis [n]" ist klar definiert, aber was meinst du mit
      "[n] bis [n] oder [n] und [n]"? - Die Verknüpfung der Operatoren ist hier nicht eindeutig. Da müsstest du wahrscheinlich mit Klammerebenen arbeiten. Erzähl noch etwas, was du mit 'bis', 'oder' und 'und' genau meinst und was die für Konsequenzen haben.

      P. S. Wo finde ich etwas über "Klammerebenen"? gp

      1. Halihallo

        "[n]" und "[n] bis [n]" ist klar definiert, aber was meinst du mit
        "[n] bis [n] oder [n] und [n]"? - Die Verknüpfung der Operatoren ist hier nicht eindeutig. Da müsstest du wahrscheinlich mit Klammerebenen arbeiten. Erzähl noch etwas, was du mit 'bis', 'oder' und 'und' genau meinst und was die für Konsequenzen haben.

        P. S. Wo finde ich etwas über "Klammerebenen"? gp

        Öm... Spielt keine Rolle. Ich hatte ein Problem mit [n] und [n] oder [n] und [n]... Ich habe mich gefragt, was das überhaupt bedeutet. Im Mathematischen Sinne müssten hier besser (um Klarheit zu schaffen) einige Klammern hin, also z. B.

        ([n] und [n]) oder ([n] und [n])

        ... Aber bei dir sind diese Dinger ja eh vorgegeben und willst sie nicht ändern...

        Ich hab einfach etwas zu weit gedacht... Ich dachte, du willst einen Parser für solche Gesetzesphrasen basteln...

        Viele Grüsse

        Philipp