Вставка атрибута в несколько узлов XML с использованием XML.modify() в SQL 2005
У меня есть документ @XML, созданный из одного оператора select.
<root>
<node>
<node1>
<targetNode>
</targetNode>
</node1>
<node1>
<targetNode>
</targetNode>
</node1>
<node1>
<targetNode>
</targetNode>
</node1>
</node>
<node>
......
</node>
</root>
Я хочу вставить xsi:nil в качестве атрибута 'targetNode' для этого документа.
@XML.modify( 'insert attribute xsi:nil {"true"} into (root/node/node1/targetNode) [1]')
Выше будет вставлен атрибут в первое вхождение targetNode в документе @XML. Оператор вставки, однако, будет работать только на одном узле. Есть ли способ вставить этот атрибут во все экземпляры targetNode в документе @XML.
3 ответа
Вы можете сделать это в select, который вы используете для создания вашего xml, используя параметр XSINILL.
http://msdn.microsoft.com/en-us/library/ms178079.aspx
(вот очень грубый пример)
--create 2 tables and put some data in them
create table node
(
id int identity(1,1) primary key,
node int
)
GO
create table node1
(
id int identity(1,1) primary key,
nodeid int foreign key references node(id),
targetnode int
)
GO
insert into node
select 1
GO 5
insert into node1
select 1,2
union
select 2,null
union
select 3,2
union
select 4,null
--
--select statement to generate the xml
SELECT TOP(1)
(SELECT
( SELECT targetnode
FROM node1
WHERE nodeid = node.id
FOR XML AUTO,
ELEMENTS XSINIL,
TYPE
)
FROM node FOR XML AUTO,
ELEMENTS,
TYPE
)
FROM node FOR XML RAW('root'),
ELEMENTS
Я нашел простое и элегантное решение в операциях DML на нескольких узлах http://blogs.msdn.com/b/denisruc/archive/2005/09/19/471562.aspx
Идея состоит в том, чтобы посчитать, сколько узлов и изменить их один за другим:
DECLARE @iCount int
SET @iCount = @var.value('count(root/node/node1/targetNode)','int')
DECLARE @i int
SET @i = 1
WHILE (@i <= @iCount)
BEGIN
@xml.modify('insert attribute xsi:nil {"true"} into (root/node/node1/targetNode)[sql:variable("@i")][1]')
SET @i = @i + 1
END
Это невозможно с помощью функции модификации. Работает только на одном узле.
Вы можете манипулировать им как строкой, хотя в некоторых случаях это определенно уродливо и, возможно, неправильно, в зависимости от фактической структуры вашего XML.
Как это:
declare @xml as xml
set @xml = '<root>
<node>
<node1>
<targetNode>
</targetNode>
</node1>
<node1>
<targetNode>
</targetNode>
</node1>
<node1>
<targetNode>
</targetNode>
</node1>
</node>
</root>
'
set @xml = replace(cast(@xml as nvarchar(max)), '<targetNode/>', '<targetNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />')
select @xml