powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите модифицировать xml
23 сообщений из 23, страница 1 из 1
Помогите модифицировать xml
    #39848414
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, приветствую!

Помогите модифицировать xml.
Хелп курил, не помогает.
Имеются 2 xml:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
declare @x xml = N'<root>
<a>
<b>1</b>
</a>
<a>
<b>2</b>
</a>
<a>
<b>3</b>
</a>
</root>'

declare @y xml = N'<root>
<a>
<b>1</b>
<d>test</d>
</a>
<a>
<b>3</b>
<d><e>test</e></d>
</a>
</root>'



Необходимо модифицировать @х нодами из @y, чтобы на выходе получился такой хмл:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
declare @x xml = N'<root>
<a>
<b>1</b>
<d>test</d>
</a>
<a>
<b>2</b>
</a>
<a>
<b>3</b>
<d><e>test</e></d>
</a>
</root>'


Т.е., в случае, если значение тега <b> в @x и @y - совпадает, то вставляем содержимое контейнера <а> из @y в @x, но без лидирующего тега <b>.

Начал так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Declare @y_n as xml, @y_id as int 

Declare cur CURSOR LOCAL FORWARD_ONLY
	for
		select t.n.query('*') as y_n, t.n.value('(b)[1]','int')  as y_id from  @y.nodes('/root/a') t(n)


Set @x.modify(
'insert (sql:variable("@y_n"))              
	into (...)
	after (...) 
')

Open cur
FETCH NEXT FROM cur into @SL, @SL_ID


Чего писать тут?
into (...)
after (...)
Не могу продраться сквозь синтаксис, хоть убейся!
... Да и вставлять нужно без лидирующего <b>, поэтому t.n.query('*') - не получится.

Помогите, очень нужен пример!
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848417
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как всегда переврал синтаксис курсора в процессе подготовки поста, и уже не исправишь.
Курсоры я писать умею, не в этом вопрос. Нужна именно модификация xml.
:-)
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848424
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Забить на курсоры.
2. Разобрать хмл в таблицы.
3. Из таблиц собрать новый хмл.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848438
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
aleks2221. Забить на курсоры.
2. Разобрать хмл в таблицы.
3. Из таблиц собрать новый хмл.
Нет, не вариант.
В оригинале, хмли - не очень большие по количеству нод (сотни - тысячи), но очень вычурные по их содержимому.
Тысячи тегов, переменного состава и т.д.
Разбирать их - не вариант.

Сервис планово-внезапно изменил представление данных, вынеся "эпизодические" данные в файл-сателлит.
Чтобы не переписывать огромный кусок всего - стоит задача "эмулировать как было", с наименьшими потерями.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848440
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xslt- преобразования надо делать
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848452
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsterРазбирать их - не вариант.Их не надо разбирать
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
declare @x xml = N'<root>
<a>
<b>1</b>
</a>
<a>
<b>2</b>
</a>
<a>
<b>3</b>
</a>
</root>';

declare @y xml = N'<root>
<a>
<b>1</b>
<d>test</d>
</a>
<a>
<b>3</b>
<d><e>test</e></d>
</a>
</root>';

with x as
(
 select
  row_number() over (order by t.n) as rn,
  t.n.value('b[1]', 'int') as b,
  t.n.query('./*') as x
 from
  @x.nodes('/root/a') t(n)
)
select
 x.x as [*],
 y.n.query('./*[local-name() != "b"]') as [*]
from
 x outer apply
 @y.nodes('/root/a[b = sql:column("x.b")]') y(n)
for xml path('a'), root('root'), type;
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848455
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsteraleks2221. Забить на курсоры.
2. Разобрать хмл в таблицы.
3. Из таблиц собрать новый хмл.
Нет, не вариант.
В оригинале, хмли - не очень большие по количеству нод (сотни - тысячи), но очень вычурные по их содержимому.
Тысячи тегов, переменного состава и т.д.
Разбирать их - не вариант.

Сервис планово-внезапно изменил представление данных, вынеся "эпизодические" данные в файл-сателлит.
Чтобы не переписывать огромный кусок всего - стоит задача "эмулировать как было", с наименьшими потерями.
Через курсор то не проблема.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
DECLARE @b int, @xml xml;

DECLARE cur CURSOR FAST_FORWARD FOR
SELECT t.c.value('b[1]', 'int') AS b
FROM @x.nodes('/root/a') AS t(c)
        INNER JOIN @y.nodes('/root/a') AS t1(c)
                ON t.c.value('b[1]', 'int') = t1.c.value('b[1]', 'int')
                
OPEN cur
FETCH NEXT FROM cur INTO @b

WHILE @@FETCH_STATUS = 0
BEGIN

    SET @xml = @y.query('/root/a[b/text() = sql:variable("@b")]')

    SET @x.modify('delete (/root/a[b/text() = sql:variable("@b")])[1]')
    
    SET @x.modify('insert sql:variable("@xml") as last into /root[1]')
    FETCH NEXT FROM cur INTO @b
END

CLOSE cur
DEALLOCATE cur

SELECT @x



Мне казалось, есть более красивый вариант, но сейчас не смог воспроизвести.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848603
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Minamoto , практически то, что нужно, но порядок тегов - поменялся местами :-)

И я немного не понял, что Вы делали.
1. Запросом из 2 xml определяется перечень ид, которые нужно модифицировать.
Далее, в курсоре
2. Извлекаем запросом ветку с ид, равным значению из курсора.
3. Урезаем значение с лишним тегом b в @x??? (а почему в @x то, мы ж туда вставляем?). Так не пойдет, т.к. в оригинале у соответствующего тега в @x - тьма атрибутов, и b в @x и @y, скажем так, не взаимозаменяемы.
Но это не принципиально, т.к., как я понимаю, можно сделать:
SET @xml.modify('delete (/root/a[b/text() = sql:variable("@b")])[1]')

4. Не понятно. Вставляем вытащенную из @y ветку последней в root.
Так не пойдет.
А способа найти нужную ноду с соответствующим ид и вставить в нее - нет?
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848606
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm, да, формально это то, что нужно.
Только я решительно них... нихт, я хотел сказать, не понял.
Сейчас попробую применить к живым данным.
Кстати, а зачем там row_number() over (order by t.n) as rn?
Чтобы "материализовать" with?
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848634
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster Minamoto , практически то, что нужно, но порядок тегов - поменялся местами :-)

И я немного не понял, что Вы делали.
1. Запросом из 2 xml определяется перечень ид, которые нужно модифицировать.
Далее, в курсоре
2. Извлекаем запросом ветку с ид, равным значению из курсора.
3. Урезаем значение с лишним тегом b в @x??? (а почему в @x то, мы ж туда вставляем?). Так не пойдет, т.к. в оригинале у соответствующего тега в @x - тьма атрибутов, и b в @x и @y, скажем так, не взаимозаменяемы.
Но это не принципиально, т.к., как я понимаю, можно сделать:
SET @xml.modify('delete (/root/a[b/text() = sql:variable("@b")])[1]')

4. Не понятно. Вставляем вытащенную из @y ветку последней в root.
Так не пойдет.
Порядок тэгов в XML не фиксирован, как набор, возвращаемый запросом без order by ;)
Можно переделать, чтобы нужный порядок был, не проблема, но вариант invm лучше, используйте его. Если не получится, тогда переделаем.
3) Насколько я понял, нужно заменить все содержимое ноды a , в которой значение b присутствует в @y . Собственно это я и делаю - грохаю полностью ноду a , и вставляю ноду a из @y с совпадающим b . Если я неправильно понял постановку - проясните, что вы имели в виду.

uaggsterА способа найти нужную ноду с соответствующим ид и вставить в нее - нет?
Способ можно найти, если вы опишете, какую конкретно ноду вы ищете и куда ее собираетесь вставить. Пока это абсолютно неочевидно.
Ну и эти вопросы актуальны, если вам не подойдет вариант invm.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848639
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsterКстати, а зачем там row_number() over (order by t.n) as rn?
Чтобы "материализовать" with?
Да низачем.

Можно даже "упростить":

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
select
    t.n.query('./*') as [*],
    y.n.query('./*[local-name() != "b"]') as [*]
from
    @x.nodes('/root/a') t(n)
    outer apply (values (t.n.value('b[1]', 'int'))) as t1(n)
    outer apply @y.nodes('/root/a[b = sql:column("t1.n")]') as y(n)
for xml path('a'), root('root'), type;
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848651
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsterКстати, а зачем там row_number() over (order by t.n) as rn?
Чтобы "материализовать" with?Можно убрать. Это остатки экспериментов.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848769
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Minamoto uaggsterА способа найти нужную ноду с соответствующим ид и вставить в нее - нет?
Способ можно найти, если вы опишете, какую конкретно ноду вы ищете и куда ее собираетесь вставить. Пока это абсолютно неочевидно.
Ну и эти вопросы актуальны, если вам не подойдет вариант invm.
Видимо, я чрезмерно упростил пример.
Тогда вся предыстория.
Когда-то был единый хмл-файл обмена, небольшой по объему, меньше 100Мб, но довольно вычурный по структуре.
Некоторая информация в этом файле - повторялась. Т.е. он был - денормализованный. А у некоторых нод - был сокращенный, в сравнении с общим случаем, набор тегов.
Сейчас (сторонние) разработчики сделали то, что грозились - вынесли часть повторяющейся информации в отдельный файл. Ну, точнее - файлы, но действия там - однотипные.
В одном файле - некая уникальная (по ИД) последовательность главных нодов, в файлах - довесках - "дополнительные" довески к этим нодам, которые "расшиваются" в зависимости от, возможно повторяющихся ключей, значение которых имеется внутри этой родителькой ноды, но которые могут и не присутствовать для некоторых нод из родительского файла.
Нормализовали, они, короче говоря, файл.

Стоит задача - синтезировать из пары родительский файл - довесок - исходный "одиночный" файл.
Т.е. взять исходный файл, и добавить в него данные довесков, ориентируясь на совпадение ключевых тегов.

Т.е. если значение некого тега b, расположенного в контейнере а, совпали и в первом, и во втором файле, все теги из контейнера а второго файла должны быть добавлены в контейнер а первого файла, в идеале - в конец этого контейнера , с совпавшим ИД.

Вариант invm - хорош, и вроде бы - решает проблему, однако, скорее всего, использовать я его не смогу, т.к. в реальности xml имеет заголовок и подвал, да и места, куда надо добавить значения - они тоже спрятаны в глубине иерархии, причем находятся в ней на среднем где-то уровне.
Т.е. выглядит примерно как:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
<root>
  <head>Тут куча тегов</head>
  <level1>
    <level2>
      <a>
        <b>1</b>
        <level3>Тут куча тегов</level3>
      </a>
      <a>
        <b>2</b>
      </a>
    </level2>
  </level1>
  <level1>
    <level2>
      <a>
        <b>3</b>
        <level3>Тут куча тегов</level3>
        <level3>Тут куча тегов</level3>
      </a>
    </level2>
  </level1>
  <foot>Тут куча тегов</foot>
</root>


Вот как то так.
Поэтому и родилась мысль - пройтись курсором и вставлять кусочки из второго файла.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848788
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster, тогда придется объединить оба подхода :)

Заодно сделал, чтобы порядок соблюдался.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
DECLARE @b int, @xml xml;

DECLARE cur CURSOR FAST_FORWARD FOR
SELECT 
    t.c.value('b[1]', 'int') AS b
FROM 
    @x.nodes('//a') AS t(c)
                
OPEN cur
FETCH NEXT FROM cur INTO @b

WHILE @@FETCH_STATUS = 0
BEGIN

    SET @xml = (
                select
                    t.n.query('./*') as [*],
                    y.n.query('./*[local-name() != "b"]') as [*]
                from
                    @x.nodes('//a[b/text() = sql:variable("@b")]') t(n)
                    outer apply @y.nodes('//a[b = sql:variable("@b")]') as y(n)
                for xml path('a')
    );
    
    SET @x.modify('insert sql:variable("@xml") after (//a[b/text() = sql:variable("@b")])[1]')
    
    SET @x.modify('delete (//a[b/text() = sql:variable("@b")])[1]')
    
    FETCH NEXT FROM cur INTO @b
END

CLOSE cur
DEALLOCATE cur

SELECT @x
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848791
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Minamotouaggster, тогда придется объединить оба подхода :)

Заодно сделал, чтобы порядок соблюдался.

ЗЫ: Весь подход расчитан на то, что значение в <b> уникально внутри файла @y. Если это может быть не так - то логика ломается, и нужно будет менять логику.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848792
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MinamotoЗЫ: Весь подход расчитан на то, что значение в <b> уникально внутри файла @y. Если это может быть не так - то логика ломается, и нужно будет менять логику.
Внутри файла @x, конечно, тоже.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848816
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MinamotoMinamotouaggster, тогда придется объединить оба подхода :)

Заодно сделал, чтобы порядок соблюдался.

ЗЫ: Весь подход расчитан на то, что значение в <b> уникально внутри файла @y. Если это может быть не так - то логика ломается, и нужно будет менять логику.
Вот внутри @x, куда вставляют - оно не уникально, а внутри @y, откуда вставляют - гарантированно уникально.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848821
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsterВот внутри @x, куда вставляют - оно не уникально, а внутри @y, откуда вставляют - гарантированно уникально.
Шо ж из вас постановку то надо клещами вытягивать, вроде же не первый день на форуме :)

Вот, вводим суррогатный ключ, чтобы не путать ноды:

Уже пора под спойлер
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
declare @x xml = N'<root>
  <head>Тут куча тегов</head>
  <level1>
    <level2>
      <a>
        <b>1</b>
        <level3>Тут куча тегов</level3>
      </a>
      <a>
        <b>1</b>
        <level3>Тут другая куча тегов</level3>
      </a>
      <a>
        <b>2</b>
      </a>
      <c />
    </level2>
  </level1>
  <level1>
    <level2>
      <a>
        <b>3</b>
        <level3>Тут куча тегов</level3>
        <level3>Тут куча тегов</level3>
      </a>
    </level2>
  </level1>
  <foot>Тут куча тегов</foot>
</root>';

declare @y xml = N'<root>
<a>
<b>1</b>
<d>test</d>
</a>
<a>
<b>3</b>
<d><e>test</e></d>
</a>
</root>';



DECLARE @b int, @rn int, @xml xml;

DECLARE cur CURSOR FAST_FORWARD FOR
SELECT 
    ROW_NUMBER() OVER (ORDER BY t.c.value('b[1]', 'int')),
    t.c.value('b[1]', 'int') AS b
FROM 
    @x.nodes('//a') AS t(c)
                
OPEN cur
FETCH NEXT FROM cur INTO @rn, @b

WHILE @@FETCH_STATUS = 0
BEGIN

    SET @xml = (
                select
                    t.n.query('./*') as [*],
                    y.n.query('./*[local-name() != "b"]') as [*]
                from
                    @x.nodes('(//a)[sql:variable("@rn")]') t(n)
                    outer apply @y.nodes('//a[b = sql:variable("@b")]') as y(n)
                for xml path('a')
    );
    
    SET @x.modify('insert sql:variable("@xml") after (//a)[sql:variable("@rn")][1]')
    
    SET @x.modify('delete (//a)[sql:variable("@rn")]')
    SELECT @x, @xml, @rn
    FETCH NEXT FROM cur INTO @rn, @b
END

CLOSE cur
DEALLOCATE cur

SELECT @x

...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848847
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Minamoto , большое спасибо. Наверное, это оно.
По моему, я даже понял решение.
Воспроизвести только, в чуть отличающемся случае - не смогу.

Вы какое-нибудь пособие for dummies по xQuery посоветовать не можете?
Потому, что я либо не тот MSDN читаю, либо не тем способом, либо воспринимаю не тем органом, который необходим для его восприятия.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848853
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggster Minamoto , большое спасибо. Наверное, это оно.
По моему, я даже понял решение.
Воспроизвести только, в чуть отличающемся случае - не смогу.

Вы какое-нибудь пособие for dummies по xQuery посоветовать не можете?
Потому, что я либо не тот MSDN читаю, либо не тем способом, либо воспринимаю не тем органом, который необходим для его восприятия.Я вообще изучал XSLT и XPath не только относительно SQL Server, так понятнее и проще - потом уже можно применить в запросах, если понимать логику ключевых слов nodes, exist, value и остальных.

Изучал последовательно здесь:
http://www.xmlmaster.org/en/article/d01/index.html, собственно, для сдачи экзамена, экзамен сдал успешно )

Если с английским проблемы, то что-то полезное для общего понимания есть на Вики, тут:
https://ru.wikipedia.org/wiki/XML
и тут:
https://ru.wikipedia.org/wiki/XPath
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39848900
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
uaggsterВы какое-нибудь пособие for dummies по xQuery посоветовать не можете?

XQuery для Sql Server имеет свою специфику, поэтому лучше сразу учить правильный вариант.

Есть такая книга: XQuery language reference. Официально бесплатна. Можно скачать, например, здесь .
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39849145
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikuaggsterВы какое-нибудь пособие for dummies по xQuery посоветовать не можете?

XQuery для Sql Server имеет свою специфику, поэтому лучше сразу учить правильный вариант.

Есть такая книга: XQuery language reference. Официально бесплатна. Можно скачать, например, здесь .Полностью согласен, лучше сразу учить правильный вариант - без специфики.

Тогда будет понятна общая логика, а изучить специфичные особенности тех или иных реализаций - это уже не проблема при наличии общего понимания.

Начинать с конкретной реализации можно тогда, когда есть 100%-я уверенность, что никогда не придется пользоваться другими реализациями.

Ну и начинать изучение лучше все же с базы - базой является XML и XML Schema.
Далее, да, можно выбрать XQuery вместо XPath, т.к., из спецификации, "XQuery Version 1.0 is an extension of XPath Version 2.0."
Книга вроде неплохая, но начинать сразу с нее я бы не рекомендовал, инфа там дается, как я успел увидеть, посмотрев по диагонали, с расчетом на то, что читающий владеет базовой терминологией.
...
Рейтинг: 0 / 0
Помогите модифицировать xml
    #39849256
uaggster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, большое спасибо.
Ушел курить маны.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите модифицировать xml
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]