Existe-t-il un moyen de construire un XPath qui évalue si la valeur d'un élément se trouve dans une liste de valeurs prédéfinie? Quelque chose qui ressemble à ceci:
/Location/Addr[State='TX or AL or MA']
Qui correspondrait aux nœuds avec des éléments d'État pour le Texas, l'Alabama ou le Massachusetts? Je sais que je peux déballer l'expression:
/Location/Addr[State='TX] or /Location/Addr[State='AL'], etc...
Mais c'est un peu lourd car les xpaths sont assez longs, tout comme la liste des valeurs. Mon google-fu ne tourne pas beaucoup sur la question ...
Vous pouvez vérifier plusieurs conditions à l'intérieur des mêmes crochets:
/Location/Addr[State='TX' or State='AL' or State='MA']
Ou si vous avez une très longue liste, vous pouvez créer une liste d'états et utiliser la fonction contains()
.
/Location/Addr[contains('TX AL MA', State)]
Cela fonctionnera bien pour les abréviations d'état à deux lettres. Si vous voulez le rendre plus robuste pour les chaînes plus longues, vous pouvez ajouter des espaces aux extrémités et vérifier _TX_
, _AL_
, Etc. (où les traits de soulignement sont des espaces).
/Location/Addr[contains(' TX AL MA ', concat(' ', State, ' '))]
Juste un nécromancement, car XPath 2.0 est arrivé.
Avec XPath 2.0, vous pouvez faire:
/Location/Addr[State=('TX', 'AL', 'MA')]
Alternativement, avec XPath 1.0, vous pouvez utiliser contient en combinaison avec string-length:
declare @tXML xml = '<svg>
<g>
<path></path>
<path data-objid="0000X1"></path>
<path data-objid="0000X2"></path>
<path data-objid="0000X3"></path>
</g>
</svg>';
-- select @tXML;
SELECT
c.p.value('(@data-objid)[1]', 'varchar(50)') AS 'DocumentID'
FROM @tXML.nodes('//node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]') AS c(p)
set @tXML.modify('delete //node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]');
select @tXML;