изменить (заменить) XML для условий

Я хочу заменить значение в теге элемента, в зависимости от его значения, а также значение другого элемента (на том же уровне, что и указанный элемент), причем оба элемента везде находятся внутри одного и того же тега родительского элемента (каждый родительский тег уникален благодаря собственному атрибуту ID). Я хочу внести изменения в различные места этой XML-переменной в хранимой процедуре.

Будучи новичком в этом, я застрял в том, как я мог изменить элементы в xml. Оба элемента присутствуют в одном и том же родительском элементе по всему документу, и каждый из этих родительских тегов имеет уникальный атрибут ID.

Любые предложения будут очень полезны. Ссылки на документы о том, как смешивать и сопоставлять «value()», «modify()» и т. д., также помогут.

DECLARE @xml xml = '
<SemanticModel xmlns="schemas.microsoft.com/sqlserver/2004/10/semanticmodeling"; xmlns:xsi="w3.org/2001/XMLSchema-instance"; xmlns:xsd="w3.org/2001/XMLSchema"; ID="G1">
    <Entities>
        <Entity ID="E1">
            <Fields>
                <Attribute ID="A1">
                    <Name>AAAA</Name>
                    <DataType>Float</DataType>
                    <Format>n0</Format>
                    <Column Name="AAAA_ID" />
                </Attribute>
                <Attribute ID="A2">
                    <Name>BBBB</Name>
                    <DataType>Integer</DataType>
                    <Format>n0</Format>
                    <Column Name="BBBB_ID" />
                </Attribute>
                <Attribute ID="A3">
                    <Name>KKKK</Name>
                    <Variations>
                        <Attribute ID="A4">
                            <Name>CCCC</Name>
                            <DataType>Float</DataType>
                            <Format>n0</Format>
                        </Attribute>
                        <Attribute ID="A5">
                            <Name>AAAA</Name>
                            <DataType>Float</DataType>
                            <Format>n0</Format>
                        </Attribute>
                    </Variations>
                    <Name>AAAA</Name>
                    <DataType>Float</DataType>
                    <Format>n0</Format>
                </Attribute>
            </Fields>
        </Entity>
    </Entities>'
DECLARE @i int = 0
;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/10/semanticmodeling' as dm, 'http://schemas.microsoft.com/analysisservices/2003/engine' as dsv, 'http://w3.org/2001/XMLSchema' as xs )
select @i = @xml.value('count(//dm:Attribute[dm:DataType="Float" and dm:Format="n0"]/dm:Format)', 'int')
select @i
while @i > 0
begin
    set @xml.modify('
         replace value of
             (//dm:Attribute[dm:DataType="Float" and dm:Format="n0"]/dm:Format/text())[1]
         with "f2"
    ')

    set @i = @i - 1
end
select @xml

Я хочу заменить значение формата «n0» на «f2» для всех атрибутов, значение формата которых равно «n0», а тип данных — «плавающий».

-Спасибо


person aaryan    schedule 25.10.2013    source источник
comment
не могли бы вы добавить пример вашего входного xml и желаемого выходного xml?   -  person Roman Pekar    schedule 25.10.2013


Ответы (1)


невозможно заменить сразу несколько значений в xml в SQL Server, есть несколько вариантов:

Я думаю, что правильным способом для вас будет решение цикла:

select @i = @data.value('count(//Attribute[DataType="Float" and Format="n0"]/Format)', 'int')

while @i > 0
begin
    set @data.modify('
         replace value of
             (//Attribute[DataType="Float" and Format="n0"]/Format/text())[1]
         with "f2"
    ')

    set @i = @i - 1
end

демонстрация скрипки sql


Если ваш xml содержит пространства имен, самым простым способом обновления, который я нашел, было бы объявить пространство имен default:

;with xmlnamespaces(default 'schemas.microsoft.com/sqlserver/2004/10/semanticmodeling')
select @i = @xml.value('count(//Attribute[DataType="Float" and Format="n0"]/Format)', 'int')

while @i > 0
begin
    set @xml.modify('
         declare default element namespace "schemas.microsoft.com/sqlserver/2004/10/semanticmodeling";
         replace value of
             (//Attribute[DataType="Float" and Format="n0"]/Format/text())[1]
         with "f2"
    ')

    set @i = @i - 1
end
select @xml
person Roman Pekar    schedule 25.10.2013
comment
XML является типизированным XML. Следовательно, обновляется только первый синглтон. - person aaryan; 25.10.2013
comment
@aaryan у вас есть пример схемы вашего xml? Я думаю, что это должно работать в любом случае - person Roman Pekar; 25.10.2013
comment
так до сих пор не работает? если да, то почему вы приняли ответ? - person Roman Pekar; 25.10.2013
comment
Это работает для меня. Но что, если бы мне пришлось использовать более одного пространства имен... Мне пришлось бы объявить их отдельно, и как я мог бы их использовать? - person aaryan; 26.10.2013
comment
не могли бы вы объяснить, как я могу использовать XQuery для восстановления XML? Заранее спасибо. - person aaryan; 27.10.2013