XPath bauen? Algorithmischer XPath? Nichts als XPath

Hallo liebe Leser. Dieser Beitrag konzentriert sich auf leicht nicht standardmäßige Anwendungen eines so bekannten Formalismus wie XPath. Jeder weiß, dass es sehr praktisch ist, Informationen aus XML- oder HTML- oder anderen * ML-Dokumenten (sowohl einfachen als auch virtuellen Text, der die oberste Ebene für die Darstellung komplexer Informationen darstellt) zu extrahieren Es gibt, um diesen Dokumenten Fragen zu stellen. Es ist jedoch bekannt, dass je besser die Frage formuliert ist, desto mehr Teil der Antwort enthält sie bereits. Daher bietet sich ein einfacher Gedanke an: Ist es möglich, in XPath geschriebene Ausdrücke als Behauptung zu verwenden, dh ein Dokument so aufzubauen, dass dieser XPath-Ausdruck wahr ist? Ich denke, es ist möglich, und dies ist das erste, was hier diskutiert wird. Und zweitens: Wenn wir lernen, wie Sie mit XPath direkt neue Elemente in einem Dokument erstellen, ist es dann möglich, XPath in eine einfache algorithmische Programmiersprache umzuwandeln? Tatsächlich weiß er, wie man auf Daten zugreift und wie man Daten erstellt. Es ist leicht vorstellbar, wie die Reihenfolge der Operatoren und der Verzweigungsoperator darauf beschrieben werden soll. Es bleibt zu überlegen, welche Zyklen darin enthalten sind und welche Funktionen es gibt. Das ist zumindest theoretisch interessant. Und das wird auch diskutiert.

XPath konstruieren


Daher beschreibt gewöhnliches XPath eine Folge von Schritten zum Durchlaufen eines Dokumentbaums, und jedem Schritt kann eine Filterbedingung (ein in eckige Klammern geschriebenes Prädikat) auferlegt werden. Als Ergebnis erhalten wir eine endliche Menge von Knoten oder eine Zahl oder eine Zeichenfolge oder einen logischen Wert. Wir interessieren uns hauptsächlich für den Fall mehrerer Knoten. Normales XPath erzeugt Knoten, die bereits im Dokument vorhanden sind. Stellen Sie sich eine hypothetische Erstellung von XPath vor, die nicht nur vorhandene Knoten zurückgibt, sondern auch neue Knoten so erstellt, dass sie vollständig mit der Abfrage übereinstimmen.

Die Idee ist sehr einfach: Im nächsten Schritt der XPath-Abfrage werden wir das Filterprädikat analysieren und Datenvarianten kompilieren, die unter diesen Filter fallen. Und dann werden wir prüfen, welche dieser Optionen bereits vorhanden sind, und die Erstellung nicht vorhandener Optionen abschließen.

Hier ist zum Beispiel eine Abfrage:

/OBJS/Var[@A=1 and @B=1 or @A=2 or @A=3]/X 

Wenn wir es als konstruierend betrachten, prüfen wir zunächst, ob das Stammelement <OBJS> vorhanden ist, und erstellen es, wenn nicht. Als nächstes kommt der Schritt Var mit einem Filter. Ich werde nicht die Regeln beschreiben, nach denen der Prädikatfilter verarbeitet wird, um die Darstellung nicht zu komplizieren. Ich werde nur sagen, dass dieser Filter die drei Datensätze, für die er wahr ist, klar beschreibt:

  1. <Var A = ”1” B = ”1” />
  2. <Var A = ”2” />
  3. <Var A = ”3” />

Wir müssen also sicherstellen, dass das <OBJS> -Element untergeordnete <Var> -Elemente mit solchen Daten enthält. Und schließlich ist der nächste Schritt X ohne Bedingung - dies bedeutet, dass jedes Var-Element ein untergeordnetes Element <X> haben muss.

Also ist alles einfach. Als Ergebnis der Anwendung eines solchen konstruierenden XPath beispielsweise auf ein Dokument

 <OBJS> <Var A=”2” /> </OBJS> 

Wir erhalten das Ausgabedokument:

 <OBJS> <Var A=”2”> <X/> </Var> <Var A=”1” B=”1”> <X/> </Var> <Var A=”3”> <X/> </Var> </OBJS> 

Gleichzeitig haben wir es ausschließlich mit XPath geschafft, ohne XSL oder ähnliches.

Algorithmischer XPath


Deshalb haben wir XPath beigebracht, wie man Daten erstellt. Bringen Sie ihm nun (ein wenig) bei, sie algorithmisch zu verarbeiten.

Die Folge von Operatoren kann durch einen üblichen logischen UND-Ausdruck beschrieben werden. Es wird streng von links nach rechts berechnet, das ist was Sie brauchen. Wenn es vollständig implementiert sein muss, müssen Sie nur sicherstellen, dass alle seine Elemente einen wahren Ausdruck zurückgeben.

 A and B and C … and Z 

Ein bedingter Operator der Form, wenn (A) dann B sonst C natürlich (und ich werde hier nichts Neues sagen), kann durch einen logischen Ausdruck beschrieben werden
 A and B or C 

Mit der Schleife ist alles etwas komplizierter. Ich wollte es einfach nicht einfach so einführen, also habe ich beschlossen, nur das Konzept einer XPath-Funktion einzuführen, die rekursiv sein kann. Und dann kann jeder Zyklus als Kette rekursiver Aufrufe mit Überprüfung der Beendigungsbedingung dargestellt werden.

Im Prinzip ist dies fast alles (in der Minimalversion). Es sind nicht einmal Variablen erforderlich - sie werden durch Elemente des aktuellen Dokuments ersetzt. Es sind nur benannte Funktionsargumente erforderlich.

Ich werde ein Beispiel geben. Angenommen, wir haben ein Dokument mit zwei Listen von Zahlen, die durch eine Reihe verschachtelter <list> -Elemente beschrieben werden:

  <a> <b> <list data="1"><list data="2"></list></list> </b> <c> <list data="3"><list data="4"></list></list></c> </a> 

Lassen Sie es notwendig sein, Listen aus dem <b> -Element und dem <c> -Element zu verketten und das Ergebnis direkt in <a> zu platzieren. Dazu müssen drei XPath-Funktionen eingeführt werden:

 concat_list($#, $##): add_list(#/self::*) and add_list(##/self::*) add_list($#): count(list) = 0 and copy_list(#/self::*) or list[add_list(#/self::*)] or true() copy_list($#): count(#/list) = 0 or create(list[@data = #/list/@data]) and (list[copy_list(#/list)] or true()) 

und füge ihnen den aufrufenden XPath hinzu:

 concat_list(/a/b,/a/c) 

Ich hoffe, liebe Leser, es wird für Sie ein wenig interessant sein, einen solchen "Code" zu verstehen. Das einzige, was ich definitiv erwähnen werde, ist create (XPATH), eine Systemfunktion, die ihr XPATH-Argument im Konstruktionsmodus ausführt.

Und jetzt, wo das alles natürlich interessant ist, ist das Programmieren ohne Variablen immer noch ziemlich schwierig. Als ich dies erkannte, führte ich vollwertige Variablen ein, die in XPath tatsächlich bereits existieren - sie beginnen mit dem Zeichen "$", aber ich fügte die Möglichkeit hinzu, ihnen mit der neuen Set-Funktion Werte zuzuweisen. Hier ist ein Beispiel für die Funktion depth_list mit zwei Argumenten - einem Verweis auf das Anfangselement, das eine verschachtelte Liste von Elementen enthält (wie im obigen Beispiel), und einer Ausgabevariablen, die die Länge der Liste enthält:

 depth_list($#, &$OUT1): set($OUT1,0) and (#/list[set($OUT1,1) and depth_list(#/list,$OUT0) and set($OUT1,max($OUT0+1,$OUT1))]) or true() 

Fazit


In der resultierenden Mikrosprache, die ich XPath Defender nannte , fügte ich einige weitere notwendige Funktionen hinzu und verwendete sie in meinem System zum Erkennen und Generieren von PGEN ++ - Programmen, um eine so wichtige Aufgabe wie die automatische Vervollständigung des Modells eines als XML-Dokument präsentierten Programms auszuführen. Mit anderen Worten, wenn es eine Textbeschreibung eines Problems gibt (zur Bestimmtheit auf Russisch), für dessen Lösung ein Programm generiert werden muss, wird diese Beschreibung erkannt und in einen geordneten Satz von Aufgabenanweisungselementen (Objekte mit Parametern) umgewandelt. Dies ist die erste Aussage, die noch keinen Plan zur Lösung des Problems enthält. Erkannte Elemente werden in ein XML-Dokument eingefügt und die Regeln werden auf sie angewendet. Sie werden sowohl in Form von einfachen Begrenzungen oder Generierungen von XPath-Anweisungen als auch in Form von Fragmenten in XPath Defender geschrieben (dies ist eine der Optionen für den Workflow). Diese Regeln validieren und ergänzen das XML-Dokumentmodell mit Elementen eines Lösungsplans. Und erst dann baut das System nach dem erhaltenen Modell ein entscheidendes Programm auf. Diese Schaltung wurde erfolgreich an einfachen Problemen der mathematischen Verarbeitung von Vektordaten getestet.

Das wichtigste Ergebnis, denke ich, ist jedoch die Tatsache, dass es möglich war zu beweisen, dass es möglich ist, eine algorithmische Programmiersprache zu erstellen, wobei fast ausschließlich die Mittel des üblichen und konstruierenden XPath verwendet wurden. Es war notwendig, nur Funktionen einzuführen.

Source: https://habr.com/ru/post/de464897/


All Articles