2009-02-11 4 views
2

У меня есть документ @XML, созданный из одного оператора select.Вставка атрибута в несколько XML-узлов с использованием XML.modify() в SQL 2005

<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. Однако оператор insert будет работать только на одном узле. Есть ли способ вставить этот атрибут во все экземпляры targetNode в документе @XML.

ответ

1

вы можете сделать это в избранных, которые вы используете для создания 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 
2

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

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

Я нашел простое и элегантное решение в операций 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