powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Преобразование одного xml в другой вид xml
14 сообщений из 14, страница 1 из 1
Преобразование одного xml в другой вид xml
    #40008373
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день. Подскажите как сделать это быстро в плане производительности при помощи xml команд MS SQL (Xquery) или может чего то еще, но именно в MS SQL без подключения сторонних библиотек и т.п.
Есть таблица с 500 тыс. записей. в ней есть поле типа xml следующего вида:
<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value1>
<number>32424244</number>
<value3>5</value1>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value1>
<value3>10</value1>
</data>

И нее нужно получить "правильную" xml:
<data>
<row>
<number>17345665</number>
</row>
<row>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
</row>
<row>
<value1>1</value1>
<value2>2</value1>
</row>
<row>
<number>32424244</number>
<value3>5</value1>
</row>
<row>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value1>
<value3>10</value1>
</row>
</data>


Известно что
1.Тэги name и number всегда идут раньше чем value1-3
2. name, number, value1-3 - это все тэги которые могут быть
3. Любого элемента может не быть

По сути нужно разбить по строчно записи. Парсинг через строку медленно работает. Можете предложить решение или хотя бы направление дать через что идти. Спасибо
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008404
Фотография Konst_One
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может через преобразование xsl попробуете?
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008429
Dimbuch®
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008436
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1,

в общем случае порядок элементов не имеет значения. Например, если такой документ загрузить в DOM, то в свойстве XML вы получите другой порядок строк.

OPENXML имеет внутренний нумератор строк, которым можно было бы воспользоваться, но я не знаю - поможет ли он как-то при разборе, не будут ли перестановки. Гарантий нет, в общем-то.
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008441
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов
mih.dim1,

в общем случае порядок элементов не имеет значения. Например, если такой документ загрузить в DOM, то в свойстве XML вы получите другой порядок строк.

OPENXML имеет внутренний нумератор строк, которым можно было бы воспользоваться, но я не знаю - поможет ли он как-то при разборе, не будут ли перестановки. Гарантий нет, в общем-то.


Поскольку это не XML, а бред. То работать с ним надо как с бредом.

REPLACE, STRING_SPLIT спасут отца русской демократии.
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008449
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1
<value3>10</value1>

Где здесь xml ?
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008455
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
env,

да ладно вам, в целом понятно чего хочет добиться ТС. полагаю что он там накосячил с закрытием тэгов (очень похоже на копипаст).

задача в целом геморная:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
<data>
    <!--группа 1-->
    <number>17345665</number>
    <!--группа 2-->
    <number>19429405</number>
       <name>Тест1</name>
       <value1>84</value1>
    <!--группа 3-->
    <number>11024248</number>
        <value1>1</value1>
        <value2>2</value2>
     <!--группа 4-->
     <number>32424244</number>
        <value3>5</value1>
     <!--группа 5-->
     <name>Тест2</name>
         <value1>6</value1>
         <value2>8</value2>
         <value3>10</value3>
</data>



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

на вскидку это будет чето типа
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
declare @x xml = '<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>'

declare @tbl table (id int, val varchar(max));
declare @knownTags table (val varchar(255));

insert into @knownTags values ('<number>'), ('<name>'), ('<value1>'), ('<value2>'), ('<value3>')

insert into @tbl 
select row_number() over (order by 1/0) -1 as [rn], cast(T.c.query('.') as varchar(max)) from @x.nodes('//*')T(c) order by 1 offset 1 row



а потом начинать шаманить с оконками в плане создания групп, повидимому какие то безумные CASE.
возможно при такой ломанной логике "новой группы" легче сделать итерационно через while / cursor;

написал только для задания вектора

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

Загружаем строку из таблицы, парсим в массив и цикл по массиву строк с проверкой ключевых слов для вставки <row>.
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008477
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1,

Можно как-то так
Код: 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.
declare @s varchar(max) = '<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>';

with a as
(
 select
  row_number() over (order by d.n) as rn,
  e.s,
  case
   when e.s like '<number>%' then 1
   when e.s like '<name>%' and lag(e.s) over (order by d.n) not like '<number>%' then 1
   else 0
  end as f
 from
  (select replace(replace(@s, '<data>', ''), '</data>', '')) a(s) cross apply
  (select cast(cast('' as xml).query('sql:column("a.s")') as varchar(max))) b(s) cross apply
  (select cast('<part>' + replace(replace(b.s, char(13), ''), char(10), '</part><part>') + '</part>' as xml)) c(x) cross apply
  c.x.nodes('/part') d(n) cross apply
  (select d.n.value('.', 'varchar(max)')) e(s)
 where
  e.s > '<'
),
b as
(
 select *, sum(f) over (order by rn) as g from a
)
select
 cast(string_agg(s, '') within group (order by rn) as xml)--as [row]
from
 b
group by
 g
for xml path('row');
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008538
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: 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.
declare @xml xml ='
<data>
<number>17345665</number>
<number>19429405</number>
<name>Тест1</name>
<value1>84</value1>
<number>11024248</number>
<value1>1</value1>
<value2>2</value2>
<number>32424244</number>
<value3>5</value3>
<name>Тест2</name>
<value1>6</value1>
<value2>8</value2>
<value3>10</value3>
</data>'

;with cte as (
	select
		row_number()over(order by (select 1)) as tag_num
		,t.c.value('local-name(.)', 'varchar(50)') as tag_name
		,t.c.value('./text()[1]', 'varchar(20)') as tag_value
		,lag(t.c.value('local-name(.)', 'varchar(50)'))over(order by (select 1)) as tag_prev
	from @xml.nodes('data/*') as t(c)
),
cte1 as (
	select
		*
		,case when (tag_name = 'number' and isnull(tag_prev,'') <> 'name') or (tag_name = 'name' and isnull(tag_prev,'') <> 'number') then 1 else 0 end as grp_flag
	from cte
),
cte2 as (
	select  
		*
		,sum(grp_flag)over(order by tag_num) as grp_num
	from cte1
)
select
	/*grp_num,*/ [name], [number], [value1], [value2], [value3]
from (select tag_name, tag_value, grp_num from cte2) t
pivot (max(tag_value) for tag_name in ([name], [number], [value1], [value2], [value3])) as pvt 
for xml raw, elements


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
<row>
  <number>17345665</number>
</row>
<row>
  <name>Тест1</name>
  <number>19429405</number>
  <value1>84</value1>
</row>
<row>
  <number>11024248</number>
  <value1>1</value1>
  <value2>2</value2>
</row>
<row>
  <number>32424244</number>
  <value3>5</value3>
</row>
<row>
  <name>Тест2</name>
  <value1>6</value1>
  <value2>8</value2>
  <value3>10</value3>
</row>
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008673
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
env
mih.dim1
<value3>10</value1>

Где здесь xml ?


Извеняйте моя опечатка.
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40008674
mih.dim1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mih.dim1,
Всем спасибо за информацию и оперативные ответы. Сейчас переключили на другую работу, но скоро проверю предложенные варианты и сообщу результат. Пока написал тупой парсинг строк в цикле. За 20 мин отработал. Но ваши варианты куда интереснее. Буду смотреть.
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40009002
Фотография HandKot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mih.dim1,

мне кажется лучше обычным реплейсом

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
declare @xml nvarchar(max) = N'
<data>
 <number>17345665</number>
 <number>19429405</number>
 <name>Тест1</name>
 <value1>84</value1>
 <number>11024248</number>
 <value1>1</value1>
 <value2>2</value2>
 <number>32424244</number>
 <value3>5</value3>
 <name>Тест2</name>
 <value1>6</value1>
 <value2>8</value2>
 <value3>10</value3>
</data>'

Select
	Cast(Replace(Replace(Replace(@xml, N'<data>', N'<data><row>'), N'<number>', N'</row><row><number>'), '</data>', '</row></data>') As 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.
<data>
  <row />
  <row>
    <number>17345665</number>
  </row>
  <row>
    <number>19429405</number>
    <name>Тест1</name>
    <value1>84</value1>
  </row>
  <row>
    <number>11024248</number>
    <value1>1</value1>
    <value2>2</value2>
  </row>
  <row>
    <number>32424244</number>
    <value3>5</value3>
    <name>Тест2</name>
    <value1>6</value1>
    <value2>8</value2>
    <value3>10</value3>
  </row>
</data>


лишний тэг "роу", можно потом прибить, если надо
...
Рейтинг: 0 / 0
Преобразование одного xml в другой вид xml
    #40009018
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HandKot

Код: 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.
<data>
  <row />
  <row>
    <number>17345665</number>
  </row>
  <row>
    <number>19429405</number>
    <name>Тест1</name>
    <value1>84</value1>
  </row>
  <row>
    <number>11024248</number>
    <value1>1</value1>
    <value2>2</value2>
  </row>
  <row>
    <number>32424244</number>
    <value3>5</value3>
    <name>Тест2</name>
    <value1>6</value1>
    <value2>8</value2>
    <value3>10</value3>
  </row>
</data>



лишний тэг "роу", можно потом прибить, если надо
Этот name и valueХ ниже, по ТЗ, ещё одна группа
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Преобразование одного xml в другой вид xml
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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