Вставка атрибута в несколько узлов XML с использованием XML.modify () в SQL 2005 - PullRequest
3 голосов
/ 11 февраля 2009

У меня есть документ @XML, созданный из одного оператора выбора.

<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 ]

3 голосов
/ 25 марта 2013

Я нашел простое и элегантное решение в операциях 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
2 голосов
/ 11 февраля 2009

Это невозможно с помощью функции модификации. Работает только на одном узле.

Вы можете манипулировать ею как строкой, хотя в некоторых случаях это определенно уродливо и, возможно, неправильно, в зависимости от фактической структуры вашего 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
1 голос
/ 11 февраля 2009

вы можете сделать это в 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
...