webentwicklung-frage-antwort-db.com.de

Gibt es einen XPath-Prozessor für das SAX-Modell?

Ich bin auf der Suche nach einem XPath-Evaluator, der nicht das gesamte DOM-Dokument neu erstellt, um nach den Knoten eines Dokuments zu suchen: Das eigentliche Ziel besteht darin, eine große Menge XML-Daten (idealerweise über 2 GB) mit dem SAX-Modell zu verwalten eignet sich für die Speicherverwaltung und gibt die Möglichkeit, nach Knoten zu suchen.

Vielen Dank für die Unterstützung!

Für alle, die sagen, dass dies nicht möglich ist: Ich habe vor kurzem nach der Frage ein Projekt mit dem Namen "saxpath" ( http://www.saxpath.org/ ) gefunden. Ich kann jedoch kein Implementierungsprojekt finden .

55
user189603

Meine aktuelle Liste (zusammengestellt aus den Ergebnissen der Websuche und den anderen Antworten) ist:

Der nächste Schritt besteht darin, die Beispiele von XMLDog zu verwenden und die Leistung all dieser Ansätze zu vergleichen. Dann sollten die Testfälle auf die unterstützten XPath-Ausdrücke erweitert werden.

15
koppor

Wir analysieren regelmäßig 1 GB + komplexe XML-Dateien mit einem SAX-Parser, der partielle DOM-Bäume extrahiert, die mit XPath bequem abgefragt werden können. Ich habe hier darüber gebloggt: http://softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html - Quellen sind verfügbar auf github = - MIT Lizenz.

11
Andreas Haufler

XPath funktioniert mit SAX, und die meisten XSLT-Prozessoren (insbesondere Saxon und Apache Xalan) unterstützen die Ausführung von XPath-Ausdrücken in XSLTs auf einem SAX-Stream, ohne den gesamten Dom zu erstellen.

Sie schaffen dies sehr grob wie folgt:

  1. Untersuchen der XPath-Ausdrücke, die sie benötigen
  2. Empfangen von SAX-Ereignissen und Testen, ob dieser Knoten von einem der XPath-Ausdrücke benötigt wird oder wird.
  3. Ignorieren des SAX-Ereignisses, wenn es nicht für die XPath-Ausdrücke verwendet wird.
  4. Pufferung wenn es benötigt wird

Wie sie zwischenspeichern, ist auch sehr interessant, weil einige hier und da einfach DOM-Fragmente erstellen, andere verwenden sehr optimierte Tabellen für eine schnelle Suche und geringeren Speicherbedarf.

Wie viel sie erreichen, hängt davon ab, welche Art von XPath-Abfragen sie finden. Wie aus der bereits veröffentlichten sächsischen Dokumentation klar hervorgeht, müssen Abfragen, die sich "aufwärts" bewegen und dann "horizontal" (Geschwister durch Geschwister) durchlaufen, das gesamte Dokument offensichtlich vorhanden sein, aber die meisten von ihnen erfordern nur wenige Knoten RAM jederzeit.

Ich bin mir ziemlich sicher, denn als ich noch jeden Tag Webapps mit Cocoon erstellte, hatten wir jedes Mal das Problem mit dem XSLT-Speicherfußabdruck, wenn wir einen "// etwas" -Ausdruck in einem XSLT verwendeten. Oft mussten wir XPath-Ausdrücke überarbeiten um eine bessere SAX-Optimierung zu ermöglichen.

9
Simone Gianni

SAX ist nur vorwärts, während XPath-Abfragen das Dokument in eine beliebige Richtung navigieren können (siehe parent::, ancestor::, preceding:: und preceding-sibling::-Achse). Ich sehe nicht, wie das überhaupt möglich wäre. Die beste Annäherung wäre eine Art DOM zum Faulenzen, aber abhängig von Ihren Abfragen kann dies einen Vorteil bringen oder nicht - es gibt immer eine Worst-Case-Abfrage wie //*[. != preceding::*].

6
Pavel Minaev

Entschuldigung, eine etwas verspätete Antwort hier - es scheint, dass dies für eine Teilmenge von XPath möglich ist - im Allgemeinen ist es sehr schwierig, da XPath vom "aktuellen" Punkt aus sowohl vorwärts als auch rückwärts passen kann. Ich kenne zwei Projekte, die es zu einem gewissen Grad mit Zustandsmaschinen lösen: http://spex.sourceforge.net & http://www.cs.umd.edu/projects/xsq . Ich habe sie nicht im Detail betrachtet, aber sie scheinen einen ähnlichen Ansatz zu verwenden.

4
Colin

Ich werde einen Plug für mein neues Projekt namens AXS werfen. Es befindet sich unter https://code.google.com/p/annotation-xpath-sax/ und die Idee ist, dass Sie Methoden mit (nur für die Vorwärtsachse) XPath -Anweisungen annotieren, und diese werden aufgerufen, wenn Der SAX-Parser befindet sich an einem entsprechenden Knoten. Also mit einem Dokument

<doc>
<nodes>
  <node name="a">text of node 1</node>
  <node name="b">text of node 2</node>
  <node otherattr="I have attributes!">text of node 3</node>
</nodes>
</doc>

sie können Dinge tun wie

@XPath("/nodes/node")
void onNode(String nodeText)
{
  // will be called with "text of node [123]"
}

oder

@XPathStart("//node[@name='']")
void onNode3(Attrs node3Attrs) { ... }

oder

@XPathEnd("/nodes/node[2]")
void iDontCareAboutNode3() throws SAXExpression
{
  throw new StopParsingExpression();
}

Natürlich ist die Bibliothek so neu, dass ich noch nicht einmal ein Release davon gemacht habe, aber sie ist MIT lizenziert. Sie können es also gerne ausprobieren und sehen, ob es Ihren Bedürfnissen entspricht. (Ich schrieb es an do HTML-Screen-Scraping mit genügend Speicherbedarf, damit ich es auf Alten Android-Geräten ausführen kann.) Wenn Sie Fehler finden, teilen Sie mir dies bitte mit googlecode site!

3
bks

Tut mir leid für die späte Antwort, aber ich habe einen einfachen XPath-Ausdruck Pfad für SAX-Parser implementiert. Es unterstützt nur Tag, Attribut mit optionalem Wert und Index aufgrund der Vorwärtsnatur von SAX. Ich habe einen Delegate-Handler erstellt, um den angegebenen Ausdruck auszuwerten, wenn der Handler ExpressionFilter implementiert. Obwohl diese Klassen in das Projekt eingebettet sind, sollte es nicht schwer sein, sie zu extrahieren.

Mehr Informationen

Beispiele - Siehe Klassen mit dem Präfix HandlerHtml

2
Kyle Kroboth

Es gibt SAX/StAX-basierte XPath-Implementierungen, die jedoch nur eine kleine Teilmenge von XPath-Ausdrücken/-Achsen unterstützen, was weitgehend auf SAX/StAX 'Forward Only' zurückzuführen ist. Die beste Alternative, die mir bekannt ist, ist VTD-XML Unterstützt den vollständigen xpath, das teilweise Laden von Dokumenten über mem-map .. und eine maximale Dokumentgröße von 256 GB. Sie benötigen jedoch eine 64-Bit-JVM, um sie voll auszuschöpfen

2
vtd-xml-author

Sie können einen XSL-Transformator an eine SAX-Eingangsquelle anschließen. Ihre Verarbeitung ist sequentiell und der XSL-Präprozessor versucht, die Eingabe abzufangen, wenn sie in das von Ihnen angegebene Ergebnis eintaucht. Sie können dies verwenden, um den Wert eines Pfads aus dem Stream zu ziehen. Dies wäre besonders praktisch, wenn Sie mehrere XPATH-Ergebnisse in einem Durchgang erstellen möchten.

Als Ergebnis erhalten Sie (normalerweise) ein XML-Dokument, aber Sie könnten Ihre erwartete Ausgabe beispielsweise aus einer StreamResult ziehen, ohne dabei zu viel Aufwand zu verursachen.

1
Carl Smotricz

Schauen Sie sich den Streaming-Modus des Saxon-SA XSLT-Prozessors an.

http://www.saxonica.com/documentation/sourcedocs/serial.html

"Die Regeln, die bestimmen, ob ein Pfadausdruck gestreamt werden kann, sind:

  • Der zu streamende Ausdruck beginnt mit einem Aufruf der Funktion document () oder doc ().
  • Der Pfadausdruck, der durch den Aufruf von doc () oder document eingeleitet wird, muss einer XPath-Untermenge entsprechen, die wie folgt definiert ist:

  • alle XPath-Ausdrücke sind zulässig, wenn sie den Regeln für Pfadausdrücke entsprechen, die in Identitätseinschränkungen in XML-Schema angezeigt werden. Diese Regeln erlauben keine Prädikate. Der erste Schritt (aber nur der erste) kann mit "//" eingeleitet werden. Der letzte Schritt kann optional die Attributachse verwenden. Alle anderen Schritte müssen einfache Achsschritte sein, die die untergeordnete Achse verwenden.

  • Darüber hinaus erlaubt Saxon, dass der Ausdruck eine Union enthält, beispielsweise doc ()/(*/ABC | / XYZ). Vereinigungen können auch in abgekürzter Form ausgedrückt werden, beispielsweise kann obiges als doc ()//(ABC | XYZ) geschrieben werden.
  • Der Ausdruck muss entweder nur Elemente oder nur Attribute oder eine Mischung aus Elementen und Attributen auswählen.

  • Einfache Filter (einer oder mehrere) werden ebenfalls unterstützt. Jeder Filter kann auf den letzten Schritt oder auf den Ausdruck als Ganzes angewendet werden und darf nur die Abwärtsauswahl vom Kontextknoten (den Achsen "self", "child", "Attribute", "descendant", "descendant-or-self" oder "Namespace") verwenden. Es darf nicht positionell sein (dh es darf nicht auf position () oder last () referenzieren und darf nicht numerisch sein: Es muss tatsächlich so sein, dass Saxon zur Kompilierzeit bestimmen kann, dass es nicht numerisch sein wird). Filter können nicht auf Gewerkschaften oder Gewerkschaftszweige angewendet werden. Bei einer Verletzung dieser Bedingungen wird der Ausdruck ohne Streaming-Optimierung ausgewertet.

  • Diese Regeln gelten, nachdem andere Optimierungsschreibvorgänge auf den Ausdruck angewendet wurden. Beispielsweise können einige FLWOR-Ausdrücke in einen Pfadausdruck umgeschrieben werden, der diese Regeln erfüllt.

  • Die Optimierung ist nur aktiviert, wenn dies explizit angefordert wird, entweder mit der Erweiterungsfunktion saxon: stream () oder mit dem Attribut saxon: read-once in einer XSLT xsl: copy-of-Anweisung oder mit dem XQuery-Pragma saxon: stream. Sie ist nur verfügbar, wenn das Stylesheet oder die Abfrage mit Saxon-SA verarbeitet wird. "

Hinweis: In der kommerziellen Version ist diese Möglichkeit höchstwahrscheinlich verfügbar. Ich habe Saxon früher ausgiebig verwendet, und es ist ein schönes Stück Arbeit.

Ich weiß nicht, ob ich dich wirklich verstehe. Soweit ich weiß, ist das SAX-Modell ereignisorientiert. Das bedeutet, dass Sie etwas tun, wenn während der Analyse ein bestimmter Knoten gefunden wird. Ja, es ist besser für das Gedächtnis, aber ich sehe nicht, wie Sie XPath dazu bringen möchten. Da SAX kein Modell baut, glaube ich nicht, dass dies möglich ist.

0
Felix Kling

Die standardmäßige javax xpath-API funktioniert technisch bereits mit Streams. javax.xml.xpath.XPathExpression kann gegen eine InputSource ausgewertet werden, die wiederum mit einer Reader konstruiert werden kann. Ich glaube nicht, dass es ein DOM unter den Covers bildet.

0
skaffman

Haben Sie auch QuiXPath https://code.google.com/p/quixpath/ ausprobiert?

0
innovimax