Est-ce que XPath a une manière définie de récupérer l'URI d'un espace de noms à partir de son abréviation lorsque l'URI n'est pas connue?

J'essaye d'écrire une requête XPath pour extraire l'URI d'un espace de noms spécifique qui utilisera toujours la même abréviation.

Exemple:

<RequestPacket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="urn:dont:really:care"> <a:Requests xmlns:queryNS="urn:uri:i:need"> <a:Request xsi:type="queryNS:GetImportantData"> <queryNS:Version>3</queryNS:Version> ... </a:Request> </a:Requests> </RequestPacket> 

J'ai besoin d'extraire l'URI qui correspond à l' queryNS noms queryNS , qui dans mon exemple serait urn:uri:i:need .

Est-ce possible? Si oui, quelqu'un pourrait-il m'aider?

J'ai essayé de l'get en utilisant la fonction namespace-uri() , mais pour ce faire, je dois spécifier un noeud, ce que je ne peux faire qu'en spécifiant les namespaces à chaque noeud (ce que j'essaie de comprendre) . Cela ressemble donc à une situation de poule et d'œuf.

Merci!

Il y a deux approches:

 DECLARE @xml XML= N'<RequestPacket xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="urn:dont:really:care"> <a:Requests xmlns:queryNS="urn:uri:i:need"> <a:Request xsi:type="queryNS:GetImportantData"> <queryNS:Version>3</queryNS:Version> ... </a:Request> </a:Requests> </RequestPacket>'; 

–use namespace-uri() contre un noeud, qui vit dans cet espace de noms

 SELECT @xml.value(N'namespace-uri((//*:Version)[1])',N'nvarchar(max)') 

– Cela pourrait être l'une des rares situations où FROM OPENXML est toujours utile . Essaye ça:

 DECLARE @docHandle INT EXEC sp_xml_preparedocument @docHandle OUTPUT, @xml; SELECT * FROM OPENXML (@docHandle, '',1) EXEC sp_xml_removedocument @docHandle 

Le résultat

 +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | id | parentid | nodetype | localname | prefix | namespaceuri | datatype | prev | text | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 0 | NULL | 1 | RequestPacket | NULL | NULL | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 2 | 0 | 2 | xsi | xmlns | NULL | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 10 | 2 | 3 | #text | NULL | NULL | NULL | NULL | http://www.w3.org/2001/XMLSchema-instance | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 3 | 0 | 2 | a | xmlns | NULL | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 11 | 3 | 3 | #text | NULL | NULL | NULL | NULL | urn:dont:really:care | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 4 | 0 | 1 | Requests | a | urn:dont:really:care | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 5 | 4 | 2 | queryNS | xmlns | NULL | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 12 | 5 | 3 | #text | NULL | NULL | NULL | NULL | urn:uri:i:need | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 6 | 4 | 1 | Request | a | urn:dont:really:care | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 7 | 6 | 2 | type | xsi | http://www.w3.org/2001/XMLSchema-instance | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 13 | 7 | 3 | #text | NULL | NULL | NULL | NULL | queryNS:GetImportantData | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 8 | 6 | 1 | Version | queryNS | urn:uri:i:need | NULL | NULL | NULL | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 14 | 8 | 3 | #text | NULL | NULL | NULL | NULL | 3 | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ | 9 | 6 | 3 | #text | NULL | NULL | NULL | 8 | ... | +----+----------+----------+---------------+---------+-------------------------------------------+----------+------+-------------------------------------------+ 

Vous pouvez utiliser le parentid et le nodetype pour find votre URI: L'atsortingbut queryNS a l'identifiant 5 . C'est le parentid de l'élément 12 , où le #text est l'URI que vous searchz. Mais cela ne peut pas être utilisé dans les requêtes adhoc / inline .

UPDATE: Vous pouvez utiliser .query()

 SELECT @xml.query( N' <root> { for $nd in //* return <nd ns="{namespace-uri($nd)}" name="{local-name($nd)}" value="{($nd/text())[1]}"> { for $attr in $nd/@* return <attr ns="{namespace-uri($attr)}" name="{local-name($attr)}" value="{$attr}" /> } </nd> } </root> '); 

Le résultat

 <root> <nd ns="" name="RequestPacket" value="" /> <nd ns="urn:dont:really:care" name="Requests" value="" /> <nd ns="urn:dont:really:care" name="Request" value="&#xA; ...&#xA; "> <attr ns="http://www.w3.org/2001/XMLSchema-instance" name="type" value="queryNS:GetImportantData" /> </nd> <nd ns="urn:uri:i:need" name="Version" value="3" /> </root> 

Utilisez simplement l'axe de l'espace de nommage:

 ssortingng(namespace::queryNS) 

ou si le préfixe d'espace de noms n'est pas connu statiquement

 ssortingng(namespace::*[name()=$prefix]) 

L'axe de l'espace de noms n'est pas disponible dans XQuery et est obsolète dans XPath 2.0+, vous pouvez donc utiliser à la place

 namespace-uri-for-prefix($prefix, $element) 

CAVEAT : Je viens de remarquer que la question était étiquetée sql-server. Je ne connais rien de l'implémentation de XPath / XQuery dans SQL Server à part le fait que ce n'est pas toujours conforme.