web-dev-qa-db-fra.com

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

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

Merci à tous pour votre aide!

Pour tous ceux qui disent que ce n'est pas possible: j'ai récemment, après avoir posé la question, trouvé un projet nommé "saxpath" ( http://www.saxpath.org/ ), mais je n'ai trouvé aucun projet de mise en oeuvre. .

55
user189603

Ma liste actuelle (compilée à partir des résultats de recherche 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 prises en charge.

15
koppor

Nous analysons régulièrement des fichiers XML complexes de plus de 1 Go à l'aide d'un analyseur SAX qui extrait des arborescences DOM partielles qui peuvent facilement être interrogées à 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 - MIT Licence.

11
Andreas Haufler

XPath fonctionne 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 d’un flux SAX sans créer le dom en entier.

Ils y parviennent 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 nœud est requis ou sera requis par l'une des expressions XPath.
  3. Ignorer l'événement SAX s'il n'est d'aucune utilité pour les expressions XPath.
  4. Buffer si nécessaire

La manière dont ils le tamponnent est également très intéressante, car alors que certains créent simplement des fragments DOM ici et là, d’autres utilisent des tables très optimisées pour une recherche rapide et une consommation de mémoire réduite.

Leur capacité d'optimisation dépend en grande partie du type de requête XPath trouvée. Comme l'explique clairement la documentation Saxon déjà publiée, les requêtes qui se déplacent "vers le haut" puis le parcourent "horizontalement" (parent par frère) exigent évidemment que le document entier soit présent, mais la plupart d'entre elles nécessitent la conservation de quelques nœuds. RAM à tout moment.

J'en suis assez sûr, car lorsque je faisais encore chaque jour une 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 avons souvent dû retravailler les expressions XPath pour permettre une meilleure optimisation SAX.

9
Simone Gianni

SAX est uniquement en avant, tandis que les requêtes XPath peuvent parcourir le document dans n’importe quelle direction (considérez les axes parent::, ancestor::, preceding:: et preceding-sibling::). 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 un avantage quelconque - il existe toujours une requête dans le pire des cas, telle que //*[. != preceding::*].

6
Pavel Minaev

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, cela est très difficile car XPath peut faire la correspondance entre le point "actuel" et le suivant. Je suis au courant de deux projets qui le résolvent en partie à l'aide de machines à états: http://spex.sourceforge.net & http://www.cs.umd.edu/projects/xsq . Je ne les ai pas examinées en détail, mais elles semblent utiliser une approche similaire.

4
Colin

Je vais lancer un plug-in pour un nouveau projet, 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 l'analyseur SAX se trouve à un noeud qui lui correspond. Donc avec un document

<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>

vous pouvez faire des choses comme

@XPath("/nodes/node")
void onNode(String 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 si nouvelle que je n’ai même pas encore publié de version, mais elle est MIT sous licence, alors n'hésitez pas à essayer et voir si elle correspond à vos besoins. (Je l'ai écritDo Écran HTML effacé avec assez de mémoire pour que je puisse l'exécuter Vieux appareils Android ...) Si vous trouvez des bogues, faites-le moi savoir en les archivant. Site .googlecode!

3
bks

Désolé pour la réponse tardive, mais j’ai implémenté un expression XPath simple chemin pour les analyseurs SAX. Il ne prend en charge que les balises, les attributs avec valeur optionnelle et les index en raison de la nature de transmission de SAX. J'ai créé un delegate Handler pour évaluer l'expression donnée lorsque le gestionnaire implémente ExpressionFilter . Bien que ces classes soient intégrées au projet, il ne devrait pas être difficile de les extraire.

Plus d'information

Exemples - Voir les classes avec le préfixe HandlerHtml

2
Kyle Kroboth

Il existe des implémentations XPath basées sur SAX/StAX, mais elles ne prennent en charge qu'un petit sous-ensemble d'expressions/axes XPath, en grande partie en raison de la nature de transmission uniquement par SAX/StAX. La meilleure alternative à ma connaissance est étendue VTD-XML =, il prend en charge l'intégralité du xpath, le 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.

2
vtd-xml-author

Ce que vous pouvez faire, c'est connecter un transformateur XSL à une source d'entrée SAX. Votre traitement sera séquentiel et le préprocesseur XSL tentera de saisir l’entrée au moment de le transformer en un résultat quelconque. Vous pouvez l'utiliser pour extraire la valeur d'un chemin du flux. Cela serait particulièrement utile si vous voulez produire plusieurs résultats XPATH différents en un seul passage.

En conséquence, vous obtiendrez (généralement) un document XML, mais vous pourriez extraire le résultat attendu de, par exemple, une StreamResult sans trop de problèmes.

1
Carl Smotricz

Regardez le mode de streaming du processeur Saxon-SA XSLT.

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

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

  • L'expression à diffuser commence par un appel à 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 pour les expressions de chemin apparaissant dans les contraintes d'identité du schéma XML. Ces règles n'autorisent 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 attributaire; toutes les autres étapes doivent être de simples étapes d'axe utilisant l'axe enfant.

  • En outre, Saxon permet à l'expression de contenir une union, par exemple doc ()/(*/ABC | / XYZ). Les syndicats peuvent également être exprimés sous forme abrégée. Par exemple, le texte ci-dessus peut être écrit sous la forme doc ()//(ABC | XYZ).
  • L'expression doit sélectionner uniquement des éléments, ou uniquement des attributs, ou un mélange d'éléments et d'attributs.

  • Les 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 ne doit utiliser que la sélection descendante à partir du nœud de contexte (axes self, enfant, attribut, descendant, descendant-ou-self ou espace de nom). Il ne doit pas être positionnel (c'est-à-dire qu'il ne doit pas faire référence à position () ou last (), et ne doit pas être numérique: en fait, il doit être tel que Saxon puisse déterminer, au moment de la compilation, que ce ne sera pas numérique). Les filtres ne peuvent pas être appliqués à des syndicats ou à des branches de syndicats. Toute violation de ces conditions entraîne l'évaluation de l'expression sans l'optimisation de la diffusion en continu.

  • 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 n'est activée que si elle est explicitement demandée, soit à l'aide de la fonction d'extension saxon: stream (), soit à l'aide de l'attribut saxon: read-once sur une instruction xSlT xsl: copy-of, ou à l'aide du flux XQuery pragma saxon:. Il est disponible uniquement si la feuille de style ou la requête est traitée à l'aide de Saxon-SA. "

Remarque: il est fort probable que dans la version commerciale, cette fonctionnalité est disponible. J'ai beaucoup utilisé Saxon un peu plus tôt, et c'est un beau travail.

Mmh je ne sais pas si je te comprends vraiment. 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é lors de l'analyse. Oui, c'est mieux pour la mémoire, mais je ne vois pas comment vous aimeriez obtenir XPath. Comme SAX ne construit pas de modèle, je ne pense pas que cela soit possible.

0
Felix Kling

L'API standard javax xpath fonctionne déjà techniquement avec les flux; javax.xml.xpath.XPathExpression peut être évalué par rapport à une InputSource, qui peut à son tour être construite avec une Reader. Je ne pense pas qu'il construise un DOM sous les couvertures.

0
skaffman

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

0
innovimax