I have some xml like:
<MyDetails>
<detail key="key1" value="value1" />
<detail key="key2" value="value2" />
<detail key="key3" value="value3" />
<detail key="key4" value="value4" />
</MyDetails>
And I want to be able to parse it in a table format of two columns Key, and Value. How can I create a SQL function to achieve this by specifying a Node path ie in this case '/MyDetails/detail' and KeyAttributeName and ValueAttributeName. I created the following function but it gives me the error:
ALTER FUNCTION [dbo].[GetXmlTable] (
@XmlSource XML,
@HierarchyPath NVARCHAR(50) = '',
@SpecificKey NVARCHAR(255) = NULL,
@KeyAttributeName NVARCHAR(50) = 'key',
@ValueAttributeName NVARCHAR(50) = 'value'
)
RETURNS @Table TABLE (
[Key] NVARCHAR(255),
[Value] NVARCHAR(500)
)
AS
BEGIN
DECLARE @KeyAttribute NVARCHAR (50) = '@' + @KeyAttributeName
DECLARE @ValueAttribute NVARCHAR (50) = '@' + @ValueAttributeName
DECLARE @Path NVARCHAR (50) = '/' + @HierarchyPath
INSERT INTO @Table
SELECT XmlElement.Attribute.value(@KeyAttribute, 'nvarchar(255)') AS [Key]
,XmlElement.Attribute.value(@ValueAttribute, 'nvarchar(500)') AS [Value]
FROM @XmlSource.nodes(@Path) AS XmlElement(Attribute)
WHERE @SpecificKey IS NULL OR XmlElement.Attribute.value(@KeyAttribute, 'nvarchar(255)') = @SpecificKey
RETURN
END
GO
Error:
Msg 8172, Level 16, State 1, Procedure GetXmlTable, Line 12 The argument 1 of the XML data type method "nodes" must be a string literal.
Looking to call the function like this:
select * from dbo.GetXmlTable(CAST('<MyDetails>
<detail key="key1" value="value1" />
<detail key="key2" value="value2" />
<detail key="key3" value="value3" />
<detail key="key4" value="value4" />
</MyDetails>' as XML), 'MyDetails/detail', default, default, default)
UPDATE---------------
I tried using sql variable syntax but the table returned is blank. Can you please point out what I might be doing wrong:
DECLARE @KeyAttr VARCHAR(50) = N'@' + @KeyAttributeName
DECLARE @ValueAttr VARCHAR(50) = N'@' + @ValueAttributeName
DECLARE @Path VARCHAR(100) = '/' + @HierarchyPath
INSERT INTO @Table
SELECT XmlElement.Attribute.value('(*[local-name() = sql:variable("@KeyAttr")])[1]', 'nvarchar(255)') AS [Key]
,XmlElement.Attribute.value('(*[local-name() = sql:variable("@ValueAttr")][1])', 'nvarchar(500)') AS [Value]
FROM @XmlSource.nodes('(*[local-name() = sql:variable("@Path")])') AS XmlElement(Attribute)
WHERE @SpecificKey IS NULL OR XmlElement.Attribute.value('(*[local-name() = sql:variable("@KeyAttr")])[1]', 'nvarchar(255)') = @SpecificKey
This query will shred your XML into a simple table;
declare @xml xml = '<MyDetails>
<detail key="key1" value="value1" />
<detail key="key2" value="value2" />
<detail key="key3" value="value3" />
<detail key="key4" value="value4" />
</MyDetails>'
select
t.c.value('@key', 'varchar(100)') as [key],
t.c.value('@value', 'varchar(100)') as value
from
@xml.nodes('/MyDetails/detail') as t(c)
The error "The argument 1 of the XML data type method "nodes" must be a string literal." means exactly what it says - you can't pass a variable as the argument to the nodes() method. You can however reference variables in the XQuery passed to Nodes() - see sql:variable() for more info.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.