Existe-t-il un processeur XPath pour le modèle SAX?

Je cherche un évaluateur XPath qui ne reconstruit pas tout le document DOM pour rechercher les nœuds d’un document: l’object est en réalité de gérer une grande quantité de données XML (idéalement sur 2 Go) avec le modèle SAX, ce qui est très bon pour la gestion de la mémoire, et donne la possibilité de rechercher des nœuds.

Merci à tous pour le soutien!

Pour tous ceux qui disent que ce n’est pas possible: récemment, après avoir posé la question, j’ai trouvé un projet nommé “saxpath” ( http://www.saxpath.org/ ), mais je ne trouve aucun projet d’implémentation.

Ma liste actuelle (compilée à partir des résultats de la recherche sur le Web et des autres réponses) est la suivante:

L’étape suivante consiste à utiliser les exemples de XMLDog et à comparer les performances de toutes ces approches. Ensuite, les scénarios de test doivent être étendus aux expressions XPath sockets en charge.

Nous analysons régulièrement des fichiers XML complexes de 1 Go et plus en utilisant un parsingur SAX qui extrait des arbres DOM partiels pouvant être interrogés de manière pratique à l’aide de XPath. J’ai blogué à ce sujet ici: http://softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html – Les sources sont disponibles sur github – Licence MIT.

XPath DOIT fonctionner avec SAX, et la plupart des processeurs XSLT (en particulier Saxon et Apache Xalan) prennent en charge l’exécution d’expressions XPath dans les XSLT sur un stream SAX sans générer la totalité du dom.

Ils parviennent à le faire très grossièrement comme suit:

  1. Examiner les expressions XPath dont ils ont besoin pour correspondre
  2. Recevoir des événements SAX et tester si ce noeud est nécessaire ou sera nécessaire pour l’une des expressions XPath.
  3. Ignorer l’événement SAX s’il n’est pas utile pour les expressions XPath.
  4. La mettre en mémoire tampon si nécessaire

Leur mise en mémoire tampon est également très intéressante car certains créent simplement des fragments DOM ici et là, tandis que d’autres utilisent des tables très optimisées pour une recherche rapide et une consommation de mémoire réduite.

La quantité d’optimisation dépend en grande partie du type de requêtes XPath qu’ils trouvent. Comme l’explique clairement la documentation Saxon déjà affichée, les requêtes qui se déplacent vers le haut, puis traversent “horizontalement” (frère ou soeur), le document nécessite évidemment que tout le document soit présent, mais la plupart ne nécessitent que quelques nœuds pour être conservés. RAM à tout moment.

Je suis assez sûr de cela parce que quand je faisais encore chaque application web en utilisant Cocoon, nous avions le problème d’empreinte mémoire XSLT chaque fois que nous utilisions une expression «// quelque chose» dans un XSLT, et nous devions souvent retravailler les expressions XPath pour permettre une meilleure optimisation SAX.

SAX est uniquement en aval, tandis que les requêtes XPath peuvent naviguer dans le document dans n’importe quelle direction (considérez parent:: , ancestor:: , preceding:: et preceding-sibling:: axis). Je ne vois pas comment cela serait possible en général. La meilleure approximation serait une sorte de DOM à chargement paresseux, mais en fonction de vos requêtes, cela peut vous apporter ou non un avantage – il y a toujours une requête la plus défavorable telle que //*[. != preceding::*] //*[. != preceding::*] .

Désolé, une réponse un peu tardive ici – il semble que cela soit possible pour un sous-ensemble de XPath – en général, c’est très difficile car XPath peut correspondre à la fois en avant et en arrière du point “actuel”. Je suis au courant de deux projets qui le résolvent dans une certaine mesure en utilisant des machines d’état: http://spex.sourceforge.net & http://www.cs.umd.edu/projects/xsq . Je ne les ai pas examinés en détail mais ils semblent utiliser une approche similaire.

Je jetterai une prise pour un nouveau projet de moi, appelé AXS. C’est à https://code.google.com/p/annotation-xpath-sax/ et l’idée est que vous annotez des méthodes avec des instructions XPath (avant-axe uniquement) et elles sont appelées lorsque l’parsingur SAX est à un nœud cela correspond. Donc avec un document

   text of node 1 text of node 2 text of node 3   

vous pouvez faire des choses comme

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

ou

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

ou

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

Bien sûr, la bibliothèque est tellement nouvelle que je ne l’ai même pas encore publiée, mais elle est sous licence MIT, alors n’hésitez pas à essayer et voir si cela correspond à vos besoins. (Je l’ai écrit pour faire un écran HTML avec des exigences de mémoire suffisamment basses pour que je puisse l’exécuter sur d’anciens appareils Android …) Si vous trouvez des bogues, faites-le moi savoir en les classant sur le site googlecode!

Désolé pour la réponse tardive, mais j’ai implémenté un chemin d’ expression XPath simple pour les parsingurs SAX. Il ne prend en charge que les balises, les atsortingbuts avec une valeur facultative et les index en raison de la nature du transfert de SAX. J’ai créé un gestionnaire de délégué pour évaluer l’expression donnée lorsque le gestionnaire implémente ExpressionFilter . Bien que ces classes soient intégrées au projet, elles ne devraient pas être difficiles à extraire.

Plus d’information

Exemples – Voir les classes avec le préfixe HandlerHtml

Il existe des implémentations XPath basées sur SAX / StAX, mais elles ne supportent qu’un petit sous-ensemble d’expressions / axes XPath en grande partie dû à la nature directe de SAX / StAX. La meilleure alternative est VTD-XML étendu, il supporte xpath complet, chargement partiel de documents via mem-map .. et une taille de document maximale de 256 Go, mais vous aurez besoin d’une JVM 64 bits pour l’utiliser à son plein potentiel

Ce que vous pouvez faire est d’accrocher un transformateur XSL à une source d’entrée SAX. Votre traitement sera séquentiel et le préprocesseur XSL tentera de capturer les données dès lors qu’il s’agit de les intégrer au résultat que vous avez spécifié. Vous pouvez l’utiliser pour extraire une valeur de chemin du stream. Cela serait particulièrement pratique si vous vouliez produire un tas de résultats XPATH différents en un seul passage.

Vous obtiendrez (généralement) un document XML en conséquence, mais vous pourriez extraire votre résultat attendu, par exemple, d’un StreamResult sans trop de tracas.

Jetez un œil au mode de diffusion du processeur XSLT de Saxon-SA.

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

“Les règles qui déterminent si une expression de chemin peut être diffusée sont:

  • L’expression à diffuser commence par un appel sur la fonction document () ou doc ​​().
  • L’expression de chemin introduite par l’appel sur doc () ou document doit être conforme à un sous-ensemble de XPath défini comme suit:

  • Toute expression XPath est acceptable si elle est conforme aux règles relatives aux expressions de chemin apparaissant dans les contraintes d’identité du schéma XML. Ces règles ne permettent aucun prédicat; la première étape (mais seulement la première) peut être introduite avec “//”; la dernière étape peut éventuellement utiliser l’axe d’atsortingbut; Toutes les autres étapes doivent être des étapes simples de l’axe utilisant l’axe enfant.

  • De plus, Saxon permet à l’expression de contenir une union, par exemple doc () / (* / ABC | / XYZ). Les unions peuvent également être exprimées sous forme abrégée, par exemple, ce qui précède peut être écrit sous la forme doc () / / (ABC | XYZ).
  • L’expression doit uniquement sélectionner des éléments, des atsortingbuts uniquement ou un mélange d’éléments et d’atsortingbuts.

  • Des filtres simples (un ou plusieurs) sont également pris en charge. Chaque filtre peut s’appliquer à la dernière étape ou à l’expression dans son ensemble et il doit uniquement utiliser la sélection descendante du nœud de contexte (les axes self, child, atsortingbute, descendant, descendant-or-self ou namespace). Il ne doit pas être positionnel (c’est-à-dire qu’il ne doit pas référencer position () ou last (), et ne doit pas être numérique: en fait, il doit être tel que Saxon puisse déterminer qu’il ne sera pas numérique). Les filtres ne peuvent pas être appliqués aux unions ou aux twigs des syndicats. Toute violation de ces conditions entraîne l’évaluation de l’expression sans l’optimisation de la diffusion.

  • Ces règles s’appliquent après que d’autres réécritures d’optimisation ont été appliquées à l’expression. Par exemple, certaines expressions FLWOR peuvent être réécrites en une expression de chemin répondant à ces règles.

  • L’optimisation est activée uniquement si elle est explicitement demandée, soit en utilisant la fonction d’extension saxon: stream (), soit l’atsortingbut saxon: read-once sur l’instruction xSLT xsl: copy-of, ou le stream XQuery pragma saxon :. Il est disponible uniquement si la feuille de style ou la requête est traitée avec Saxon-SA. ”

Remarque: Il est fort probable que cette fonctionnalité soit disponible dans la version commerciale. J’ai beaucoup utilisé Saxon plus tôt, et c’est un bon travail.

Mmh je ne sais pas si je te comprends vraiment. Pour autant que je sache, le modèle SAX est orienté événement. Cela signifie que vous faites quelque chose si un certain nœud est rencontré pendant l’parsing. Oui, c’est mieux pour la mémoire mais je ne vois pas comment vous voudriez y intégrer XPath. Comme SAX ne construit pas de modèle, je ne pense pas que ce soit possible.

L’API javax xpath standard fonctionne déjà techniquement avec les stream; javax.xml.xpath.XPathExpression peut être évalué sur un InputSource , qui peut à son tour être construit avec un Reader . Je ne pense pas qu’il construit un DOM sous les couvertures.

Avez-vous déjà essayé QuiXPath https://code.google.com/p/quixpath/ ?

Je ne pense pas que xpath fonctionne avec SAX, mais vous pouvez jeter un oeil à StAX qui est une API XML de streaming étendue pour Java.

http://en.wikipedia.org/wiki/StAX