I have a SQL function that takes a variable called attribute, which is the xml attribute I want to get the value from. xmlPath is the full XML string.
My xml looks like this:
<EventSpecificData>
<Keyword>
<Word>myWord</Word>
<Occurences>1</Occurences>
<Context>context</Context>
</Keyword>
</EventSpecificData>
I want to get the value for <Word>, so I pass in /Keyword/Word and set a variable to:
set @value = @xmlPath.value('(/EventSpecificData/@attribute)[1]', 'varchar(max)')
However, I don’t think @attribute is actually inserting the variables string. Is there another way to do this?
Here are a couple of solutions for you.
Sample data:
Get the first value from node named Word regardless of parents. Use
//to do a deep search and uselocal-name()to match node name.Provide parent node name and attribute in separate variables using
local-name()in two levels.Since the parameter to
nodeshave to be a string literal it invites to use dynamic sql to solve this. It could look something like this to make it work with your original variable content.But you should be aware of that if you use this you are wide open to SQL Injection attacks. Some devious end-user might come up with a attribute string that looks like this:
Executing the dynamic SQL with that will give you two result sets. The
select @@versionis just there to show some harmless code but it might be much worse stuff in there.You can use
quotename()to prevent the SQL injection attack. It will at least prevent the attempt made by me.Is the last version using
quotename()safe? Have a look at this article by Erland Sommarskog The Curse and Blessings of Dynamic SQL.Quote: