Как заменить тег другим файлом в sql server XML - PullRequest
0 голосов
/ 16 апреля 2020

Я работаю над таблицей на сервере sql, который хранит файл xml в столбце. В этом файле xml я делаю некоторые изменения. Файл XML выглядит следующим образом:

<Report version=1>
 <Title>
   <Student>
         <InputNumber type="int" min="0" max="100" name="age" description="Age 
          of student">
            <Value>20</Value>
         </InputNumber>
         <InputNumber type="int" min="0" max="100" name="height" 
         description="height of student">
             <Value>170</Value>
         </InputNumber>
   </Student>
 </Title>
</Report>

Я понимаю использование функции изменения для обновления атрибутов или текста, присутствующего между тегами, как:

UPDATE student
SET dataxml.modify('replace value of (/Report/@version)[1] with "2"')
WHERE id=10
or
UPDATE student
SET dataxml.modify('replace value of (/Report/Title/Student/InputNumber[1]/Value[1]/text())[1] with "21"')
WHERE id=10

Но теперь я хочу заменить весь тег с другим тегом, например

         <InputNumber type="int" min="0" max="100" name="height" 
         description="height of student">
             <Value>170</Value>
         </InputNumber>

с

         <InputText name="height" 
         description="height of student">
             <Value>170 cm</Value>
         </InputText>

Я нашел что-то в inte rnet, как это и попытался.

Update Student
   set dataxml = replace(cast(dataxml as nvarchar(max)),'/Report/Title/Student/InputNumber[2]>','InputText>')
WHERE id=10

Он говорит, что успешно обновлен , Но я не вижу изменений в XML. Как я могу это сделать?

1 Ответ

1 голос
/ 16 апреля 2020

Прежде всего: Ваш XML недействителен. Атрибут version=1 должен быть version="1". Второе: глагол tag - это всего лишь одна разметка, подобная <Student> или </Student>, но весь узел с атрибутами и вложенными подузлами называется node или - как специальный тип узла - element .

Теперь к вашей проблеме:

Нам нужна объявленная таблица для имитации вашей проблемы:

DECLARE @student TABLE(ID INT IDENTITY, dataxml XML);
INSERT INTO @student VALUES
(N'<Report version="1">
 <Title>
   <Student>
         <InputNumber type="int" min="0" max="100" name="age" description="Age of student">
            <Value>20</Value>
         </InputNumber>
         <InputNumber type="int" min="0" max="100" name="height" description="height of student">
             <Value>170</Value>
         </InputNumber>
   </Student>
 </Title>
</Report>');

- Это это новый элемент, который мы хотим вставить (лучше: хотите использовать для замены другого)

DECLARE @newElement XML=
N'<InputText name="height" description="height of student">
    <Value>170 cm</Value>
  </InputText>';

--approach one calls `.modify()` twice:

UPDATE @student SET dataxml.modify('insert sql:variable("@newElement") after (/Report/Title/Student/InputNumber[@name="height"])[1]');
UPDATE @student SET dataxml.modify('delete (/Report/Title/Student/InputNumber[@name="height"])[1]');

SELECT * FROM @student; 

- второй подход использует FLWOR-XQuery

UPDATE @student SET dataxml=dataxml.query('<Report version="{/Report/@version}">
                                           {<Title> 
                                            <Student>
                                            {
                                            for $elmt in /Report/Title/Student/*
                                            return
                                            if(local-name($elmt)="InputNumber" and $elmt[@name="height"]) then
                                               <InputText name="height" description="height of student">
                                                   <Value>{$elmt/Value/text()} cm</Value>
                                               </InputText>
                                            else
                                                $elmt
                                            }
                                            </Student>
                                           </Title>}
                                           </Report>');

Обе идеи вкратце:

1) Мы вставляем новый элемент сразу после того, который должен быть заменен, и удаляем его в отдельном шаге.

2) Мы воссоздаем XML через XQuery, пропуская через внутренний список узлов в <Student> и вставьте новое содержимое вместо существующего узла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...