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 .
.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="
 ...
 "> <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.