Reputation: 1895
I'm trying to write a SP in SQL Server 2008 where if the input is a valid XML and a XPATH i want to retrieve the value of that XPATH:
For example if i have:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<genRetrieve xmlns:v1="http://xxxxxxxxxxxxxxxxxxxxx">
<checkRetrieve>
<party>
<user>
<first>JOHN</first>
<last>SMITH</last>
</user>
<media />
</party>
</checkRetrieve>
</genRetrieve>
</soapenv:Body>
</soapenv:Envelope>
And the XPATH is :
/*[local-name() = "Envelope"][1]/*[local-name() = "Body"][1]/genRetrieve[1]/checkRetrieve[1]/party[1]/user[1]/first[1]
I need to grab "JOHN" and return it.
I tried the below
DECLARE @xml xml,
@xpath nvarchar(max),
@output nvarchar(100),
@query nvarchar(max)
SET @xml = @userINPUT
SET xpath = '/*[local-name() = "Envelope"][1]/*[local-name() = "Body"][1]/genRetrieve[1]/checkRetrieve[1]/party[1]/user[1]/first[1]' + '/text()'
SET @output = ''
select @output = @xml.query('sql:variable("@xpath")')
But instead of the value i just get the full XPATH string i passed as argument in return. I also tried dynamic query:
SET @query = 'SELECT @xml.query(N''' + @xpath + '/text()'')'
print @query
EXECUTE(@query)
But it gives "Must declare the scalar variable "@xml" erorr
Upvotes: 1
Views: 1775
Reputation: 107267
The xmlns xmlns:v1="http://xxxxxxxxxxxxxxxxxxxxx"
is a bit of a red herring - although it is declared, no nodes are actually defined in it. (Possibly unintended?)
You can use namespaces with XQuery with WITH NAMESPACES
, which will allow you to avoid using the agnostic local-name()
:
WITH XMLNAMESPACES(
'http://schemas.xmlsoap.org/soap/envelope/' AS soapenv,
'http://xxxxxxxxxxxxxxxxxxxxx' AS v1)
SELECT
Nodes.node.value('(first)[1]', 'varchar(50)') AS FirstName,
Nodes.node.value('(last)[1]', 'varchar(50)') AS LastName
FROM
@xml.nodes('/soapenv:Envelope/soapenv:Body/genRetrieve/checkRetrieve/party/user')
AS Nodes(node);
Edit Apologies, I missed the point you wanted to do this dynamically:
DECLARE @query NVARCHAR(MAX) =
N'WITH XMLNAMESPACES(
''http://schemas.xmlsoap.org/soap/envelope/'' AS soapenv,
''http://xxxxxxxxxxxxxxxxxxxxx'' AS v1)
SELECT
Nodes.node.value(''(' + @xpath + ')[1]'', ''varchar(50)'') AS FirstName
FROM
@xml.nodes(''.'') AS Nodes(node)';
exec sp_executesql @query, N'@xml xml', @xml = @xml;
Upvotes: 1