2008-09-02 8 views
8

J'ai une application qui extrait des données à partir d'un fichier XML en utilisant XPath. Si un noeud dans ce fichier source XML est manquant, je veux retourner la valeur "N/A" (un peu comme la fonction Oracle NVL). L'astuce est que l'application ne supporte pas XSLT; Je voudrais faire cela en utilisant XPath et XPath seul.Puis-je créer une valeur pour une balise manquante dans XPath?

Est-ce possible?

Répondre

5

Cela peut être fait, mais seulement si la valeur de retour lorsque le noeud existe est la valeur de chaîne du nœud, pas le nœud lui-même. Le XPath

substring(concat("N/A", /foo/baz), 4 * number(boolean(/foo/baz))) 

retourne la valeur de chaîne de l'élément baz si elle existe, sinon la chaîne « N/A ».

Généraliser l'approche:

substring(concat($null-value, $node), 
      (string-length($null-value) + 1) * number(boolean($node))) 

$null-value est la chaîne de valeur nulle et $node l'expression pour sélectionner le nœud. Notez que si $node évalue un ensemble de noeuds contenant plusieurs noeuds, la valeur de chaîne du premier noeud est utilisée.

1

Cela peut être fait avec XPath 1.0. Disons que vous avez

<foo> 
    <bar/> 
</foo> 

Si vous voulez tester si foo a un enfant baz,

substring("N/A", 4 * number(boolean(/foo/baz))) 

retournera « N/A » si l'expression /foo/baz retourne un ensemble vide de noeuds, sinon il retourne une chaîne vide.

1

@jelovirt

Donc, si je comprends bien, nous concaténer la réponse par défaut et la valeur du nœud, puis prendre le sous-ensemble correct de la chaîne résultante en testant l'existence du nœud pour définir la décalage à zéro ou la position juste après ma chaîne par défaut. C'est la torsion la plus perverse d'une langue que j'ai jamais vue. (Je l'adore!)

Pour clarifier ce que vous avez dit, cette approche fonctionne lorsque le noeud est manquant, pas quand le noeud est vide. Mais en remplaçant "number (boolean ($ node))" par "string-length ($ node)", il fonctionnera sur les nœuds vides à la place.

2

Pour les nœuds vides, vous avez besoin

boolean(string-length($node)) 

(Vous pouvez omettre l'appel à number() que la distribution de booléen au numéro est implicite ici.)