Reputation: 253
I have next XML:
SET @MyXML =
'
<pairs>
<p>
<Name>France</Name>
<Val>Paris</Val>
</p>
<p>
<Name>England</Name>
<Val>London</Val>
</p>
<p>
<Name>Spain</Name>
<Val>Madrid</Val>
</p>
</pairs>
'
I need to get data from this XML in this way - I've set parameter "England" and get "London". My code is next, but it's not working:
SELECT
Tab.Col.query('p/.[(Val)[1] cast as xs:string? = "England"]') AS [Capital]
FROM
@MyXML.nodes('//pairs') Tab(Col)
What I miss? Thanks!
Upvotes: 2
Views: 176
Reputation: 2433
Your XQuery object is incorrectly constructed. This will get the <p>
which has the <name>
as "England"
and then the return the <Val>
tag.
SELECT
Tab.Col.value('((p[Name="England"]/Val/text())[1])', 'varchar(max)') AS [Capital]
FROM
@MyXML.nodes('//pairs') Tab(Col)
Upvotes: 2
Reputation: 58685
You can isolate the <p>
tag in the nodes path and simplify your SELECT.
This gives a list of all Countries and Capitals:
SELECT
T.c.value('(Name)[1]','nvarchar(100)') AS Country
,T.c.value('(Val)[1]','nvarchar(100)') AS Capital
FROM
@MyXML.nodes('/pairs/p') T(c)
The syntax is no different in the WHERE clause, so you can just apply a parameter there:
declare @param nvarchar(100) = 'England'
SELECT
T.c.value('(Val)[1]','nvarchar(100)') AS Capital
FROM
@MyXML.nodes('/pairs/p') T(c)
WHERE T.c.value('(Name)[1]','nvarchar(100)') = @Param
Here is a complete test script that does both.
declare @MyXML xml;
SET @MyXML =
'
<pairs>
<p>
<Name>France</Name>
<Val>Paris</Val>
</p>
<p>
<Name>England</Name>
<Val>London</Val>
</p>
<p>
<Name>Spain</Name>
<Val>Madrid</Val>
</p>
</pairs>
'
SELECT
T.c.value('(Name)[1]','nvarchar(100)') AS Country
,T.c.value('(Val)[1]','nvarchar(100)') AS Capital
FROM
@MyXML.nodes('/pairs/p') T(c)
declare @param nvarchar(100) = 'England'
SELECT
T.c.value('(Val)[1]','nvarchar(100)') AS Capital
FROM
@MyXML.nodes('/pairs/p') T(c)
WHERE T.c.value('(Name)[1]','nvarchar(100)') = @Param
Upvotes: 0
Reputation: 67291
You try it a bit to complicated:
DECLARE @MyXML XML =
N'<pairs>
<p>
<Name>France</Name>
<Val>Paris</Val>
</p>
<p>
<Name>England</Name>
<Val>London</Val>
</p>
<p>
<Name>Spain</Name>
<Val>Madrid</Val>
</p>
</pairs>';
DECLARE @param NVARCHAR(100)=N'England';
SELECT
Tab.Col.query('(p[Name=sql:variable("@param")]/Val)[1]') AS [Capital]
FROM
@MyXML.nodes('/pairs') Tab(Col)
Even better
SELECT
p.value('Val[1]','nvarchar(max)') AS [Capital]
FROM
@MyXML.nodes('/pairs/p[Name=sql:variable("@param")]') One(p)
Or as a one liner
SELECT @MyXml.value('(/pairs/p[Name=sql:variable("@param")]/Val)[1]','nvarchar(max)') AS [Capital]
Upvotes: 2
Reputation: 26846
You can do it even without complicated XPath queries like this:
select Tab.Col.value('Val[1]', 'nvarchar(max)') AS [Capital]
from @MyXML.nodes('/pairs/p') as Tab(Col)
where Tab.Col.value('Name[1]', 'nvarchar(max)') = 'England'
Upvotes: 1