Générer/obtenir xpath de nœud XML, java
Je suis intéressé par des conseils/pseudo code/explication plutôt que de la mise en œuvre effective.
- Je voudrais aller à la fosse du document xml, l'ensemble de ses nœuds
- Vérifier le nœud attribut existence
Cas si le nœud n'a pas d'attribut, get/generate String with value of its xpath
Cas si le nœud n'ont attributs, itérer creux liste d'attributs et de créer xpath pour chaque attribut, y compris le nœud.
Parole de conseils? J'espère que vous apporter des éléments utiles intel
EDIT:
Des raisons pour cela est .. je suis en train d'écrire des tests automatisés dans jmeter, donc pour chaque demande, j'ai besoin de vérifier que la demande a effectivement fait son travail, donc je suis en affirmant résultats en obtenant les valeurs des nœuds xpath.(plus d'info pertinente)
Lorsque la demande est faible sa pas de problème pour créer affirme par la main, mais pour les grandes ses vraiment une douleur dans le .. (plus d'info pertinente)
BOUNTY :
Je suis à la recherche pour java approche
Objectif
Mon objectif est de parvenir à la suite de cette ex fichier xml :
<root>
<elemA>one</elemA>
<elemA attribute1='first' attribute2='second'>two</elemA>
<elemB>three</elemB>
<elemA>four</elemA>
<elemC>
<elemB>five</elemB>
</elemC>
</root>
de produire les éléments suivants :
//root[1]/elemA[1]='one'
//root[1]/elemA[2]='two'
//root[1]/elemA[2][@attribute1='first']
//root[1]/elemA[2][@attribute2='second']
//root[1]/elemB[1]='three'
//root[1]/elemA[3]='four'
//root[1]/elemC[1]/elemB[1]='five'
Expliqué :
- Si la valeur du nœud/texte n'est pas null/zero, obtenir xpath , ajoutez = 'nodevalue' pour l'affirmation but
- Si le nœud a les attributs de créer affirmer pour eux aussi
BOUNTY MISE À JOUR :
J'ai trouvé cet exemple, il ne produit pas les résultats corrects , mais je suis à la recherche de quelque chose comme ceci:
http://www.coderanch.com/how-to/java/SAXCreateXPath
- Bonne question, +1. Voir ma réponse complète XSLT 1.0 solution qui prend un paramètre qui contient un node-set et produit une expression XPath pour chaque nœud dans ce node-set. Les nœuds peuvent être de tout type: document-nœud, élément, nœud texte, d'attribut, de commentaire, de PI, de l'espace de noms.
- Ce genre d'expression XPath voulez-vous bien? Vous pouvez simplement prendre l'index de chaque élément dans l'un de ses parents
getChildren()
nodelist et de créer un xpath comme/*[5]/*[2]/*[8]/@yourattr
. Mais si vous voulez faire valoir des résultats, ne devriez-vous pas être en train de faire l'inverse? Écrire une expression xpath qui retourne vrai si votre XML est correct, et false si elle ne l'est pas, alors l'évaluer? - Je veux créer des requêtes xpath de la demande, je l'envoyer(si je peux l'utiliser pour vérifier les résultats), pas l'autre manière autour. J'ai mis à jour ma question
- Il y a des trous dans la mise à jour de votre question. Que faire si un élément a plus d'un nœud de texte comme dans:
<x>text 1<y/>text 2</x>
Comment le voulait processus de solution un tel élément? Je vais mettre à jour ma réponse avec à la fois une transformation XSLT solution et une solution C# (mon Java est un peu rouillé) -- ce que ce sera utile pour vous? - Novatchev merci pour les commentaires, aussi loin que je peux voir, ce cas ne se produit jamais dans mes fichiers xml, et je ne pense pas que ça. Comme BalusC a suggéré que je pourrais laisser d'exécution java XSLT, si elle produit de bons résultats à titre d'exemple que j'ai posté ci-dessus. tnx
- C'est bon à savoir, merci. Donc, il peut être utile si vous mettez cette précision dans la question elle-même. À partir de votre dernier commentaire, je peux conclure que le fait d'aller de l'avant avec XSLT et éventuellement C# solution sera de valeur pour vous?
- Novatchev oui, il serait plus que bienvenue. Merci
- J'ai produit une complète et très court (30 lignes) XSLT c'est aussi une solution facile à comprendre et permet de résoudre votre problème exactement.
- J'ai aussi ajouté une étape-par-étape de l'explication de la solution. Je vous remercie pour votre appréciation.
- Novatchev merci vraiment l'apprécier
- Merci pour la nouvelle raffinement du problème. Oui, c'était facile à ajuster ma solution pour traiter le format mis à jour. J'ai mis à jour dans ma réponse à la fois le code et les explications. Merci de fournir ce problème de nice.
- Double Possible de comment faire pour récupérer correspondant xpath
Vous devez vous connecter pour publier un commentaire.
Mise à jour:
@c0mrade a mis à jour sa question. Voici une solution:
Cette transformation XSLT:
lorsqu'il est appliqué sur le document XML fourni par le:
produit exactement le voulait, résultat correct:
Lorsqu'il est appliqué à la nouvelle-document fourni par @c0mrade:
de nouveau le résultat correct est produit:
Explication:
Uniquement des éléments qui n'ont pas d'enfants, ou avoir des attributs sont appariés et traitées.
Pour cet élément, si ce n'est pas avoir des enfants-les éléments de l'ensemble de ses ancêtres, ou de soi que les éléments sont traités dans un mode spécifique, nommé
'path'
. Puis le"='theValue'"
partie est sortie et un caractère NL.Tous les attributs de la correspondance de l'élément sont ensuite traitées.
Puis enfin, les modèles sont appliqués à tous les enfants-éléments.
De traitement d'un élément dans le
'path'
mode est simple: Un/
personnage et le nom de l'élément sont de sortie. Ensuite, si il y a des précédents, les frères et sœurs avec le même nom, un "[numPrecSiblings+1] est sortie.Traitement des attributs est simple: la Première de toutes les
ancestor-or-self::
éléments de son parent sont traitées dans'path'
mode, la [attrName=attrValue] la partie est de sortie, suivi par un caractère NL.Ne remarque:
Noms qui sont dans un espace de noms sont affichés sans aucun problème et dans leur forme lisible.
À l'aide de lisibilité, un indice de
[1]
n'est jamais affiché.Ci-dessous est ma première réponse (peut être ignoré)
Ici est un pur XSLT 1.0 solution:
Ci-dessous est un exemple de document xml et une feuille de style qui prend un node-set de paramètre et produit une expression XPath valide pour tous les membres-nœud.
la feuille de style (buildPath.xsl):
source xml (buildPath.xml):
Résultat:
Ici est de savoir comment cela peut être fait avec SAX:
Il peut être testé avec:
Ceci va produire le résultat désiré:
elementNameCount
compte les occurrences d'un élément particulier de type (nom) à l'échelle mondiale à travers le document, indépendamment du fait qu'ils sont frères et sœurs, cousins et cousines (même niveau, mais les différents parent), ou à des niveaux différents. Mais vous sortie XPath"[" + count + "]"
comme si nous sommes en position de comptage entre frères et sœurs. Cela va clairement à l'échec pour les non négligeable de documents. Droit? E. g.<a><a>foo</a></a>
serait sortie de//a[1]/a[2]='foo'
, et la[2]
est incorrect.Avec jOOX (un jquery API port de Java, avertissement, je travaille pour la société derrière la bibliothèque), vous pouvez presque atteindre ce que vous voulez en une seule instruction:
Si le document est votre modèle de document:
Ceci va produire
Par "presque", je veux dire que jOOX n'a pas (encore) de soutien de contrepartie/mappage d'attributs. Par conséquent, vos attributs ne produit aucune sortie. Ce sera mis en œuvre dans un proche avenir, si.
$
? C'est légal de Java?!JOOX.$
. Je vais mettre à jour la réponseCe code fonctionne avec deux hypothèses: vous n'utilisez pas les espaces de noms et il n'y a pas mélangé des éléments de contenu. La limitation de l'espace de noms n'est pas grave, mais ce serait faire de votre expression XPath beaucoup plus difficile à lire, comme chaque élément serait quelque chose comme
*:<name>[namespace-uri()='<nsuri>'][<index>]
, mais sinon il est facile à mettre en œuvre. Contenu mixte, d'autre part rendre l'utilisation de xpath très fastidieux, car vous devriez être en mesure d'évaluer individuellement les deuxième, troisième et ainsi de suite nœud de texte au sein d'un élément.quelque chose comme ça.
UPD:
et concaténer liste finale pour le final de xpath.
ne pense pas que les attributs ne sera pas un problème.
J'ai fait une tâche similaire une fois. La principale idée est que vous pouvez utiliser l'index de l'élément dans la xpath. Par exemple, dans le code xml suivant
xpath pour la deuxième
<el/>
sera/root[1]/el[2]
xpath (index 1). Cela se lit comme "prendre la première racine, puis prendre la deuxième à partir de tous les éléments avec le nom el". Donc, l'élémentsomething
n'affecte pas l'indexation des élémentsel
. Ainsi, vous pouvez, en théorie, de créer un xpath pour chaque élément spécifique dans votre xml. Dans la pratique, j'ai accompli cela en marchant l'arbre recursevely et en mémorisant des informations sur les éléments et leur index le long de la voie.La création de xpath référencement attribut spécifique de l'élément, puis a été juste en ajoutant '/@attrName' à l'élément de xpath.
J'ai écrit une méthode retourne le chemin absolu d'un élément dans le Pratique XML de la bibliothèque. Pour vous donner une idée de comment cela fonctionne, voici un extrait d'une de la les tests unitaires:
Donc, vous pouvez le répéter à travers le document, appliquez vos tests, et de l'utiliser pour retourner le XPath. Ou, ce qui est probablement mieux, c'est que vous pouvez utiliser la XPath-fondé des assertions à partir de cette même bibliothèque.
J'ai fait exactement la même chose la semaine dernière pour le traitement de mon xml à solr format compatible.
Depuis que tu voulais un pseudo-code: c'est de Cette façon que j'ai accompli cela.
//Vous pouvez ignorer la référence à la mère et de l'enfant.
1_ Initialiser un noeud personnalisé objet: NodeObjectVO {String nodeName, chemin de la Chaîne, Liste attr, NodeObjectVO parent, Liste enfant}
2_ Créer une liste vide
3_ Créer un dom représentation de xml et de réitérer thro le nœud. Pour chaque nœud, obtenir les informations correspondantes. Toutes les informations comme le nom du Nœud,les noms d'attribut et la valeur doit être facilement accessible depuis les dom objet. ( Vous avez besoin de vérifier les dom NodeType, le code doit ignorer les instructions de traitement et de la plaine des nœuds de texte.)
//Code de Ballonnement de l'avertissement.
4_ La seule partie difficile est d'obtenir le chemin d'accès. J'ai créé un processus itératif d'utilité méthode pour obtenir le xpath chaîne de NodeElement. (While(nœud.Parent != null ) { path+=node.parent.nodeName}.
(Vous pouvez également l'obtenir par le maintien d'un chemin d'accès global variable, qui conserve la trace du chemin d'accès parent pour chaque itération.)
5_ Dans la méthode de définition de setAttributes (Liste), je vais ajouter le tracé de l'objet avec tous les attributs disponibles. (un chemin d'accès avec tous les attributs disponibles. Pas une liste de chemin avec chaque combinaison possible des attributs. Vous voulez peut-être faire someother façon. )
6_ Ajouter le NodeObjectVO à la liste.
7_ Maintenant, nous avons un appartement (pas hierrarchial) liste de Noeud personnalisé Objets, qui ont toutes les informations dont j'ai besoin.
(Note: Comme je l'ai mentionné, j'ai de maintenir la relation de parent-enfant, vous devriez probablement sauter cette partie. Il y a une possibilité de code ballonnements, particulièrement lors de la getparentpath. Pour les petites xml ce n'était pas un problème, mais c'est un sujet de préoccupation pour les grandes xml).