Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
Ту4а
Member

Откуда:
Сообщений: 5
Хранимая процедура собирает XML. Формирование текстовика надо делать на клиенте.
Вложенных блоков(узлов) много, xml большой
Необходимо вернуть из процедуры не типом XML. а построчно в виде результирующего селекта
Другими словами вернуть построчно всё дерево (хорошо бы с Identity строки)

Declare @x xml
select @x ='
<Root>
    <ИмяФайла>94104.XML</ИмяФайла>
    <ЗаголовокФайла>
        <ВерсияФормата>07</ВерсияФормата>
        <ТипФайла>ВНЕШНИЙ</ТипФайла>
        <ПрограммаПодготовкиДанных>
            <НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
            <Версия>02</Версия>
        </ПрограммаПодготовкиДанных>
        <ИсточникДанных>Р</ИсточникДанных>
    </ЗаголовокФайла>
    <!--...и так далее -->
</Root>
'
SELECT T.c.query('.') AS result
  FROM  @x.nodes('//*') as T(c)
--------------------------------------------------
------вернет-------------
/*
<Root><ИмяФайла>94104.XML</ИмяФайла><ЗаголовокФайла><ВерсияФормата>07</ВерсияФормата><ТипФайла>ВНЕШНИЙ</ТипФайла><ПрограммаПодготовкиДанных><НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы><Версия>02</Версия></ПрограммаПодготовкиДанных><ИсточникДанных>Р</ИсточникДанных></ЗаголовокФайла><!--...и так далее --></Root>
<ИмяФайла>94104.XML</ИмяФайла>
<ЗаголовокФайла><ВерсияФормата>07</ВерсияФормата><ТипФайла>ВНЕШНИЙ</ТипФайла><ПрограммаПодготовкиДанных><НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы><Версия>02</Версия></ПрограммаПодготовкиДанных><ИсточникДанных>Р</ИсточникДанных></ЗаголовокФайла>
<ВерсияФормата>07</ВерсияФормата>
<ТипФайла>ВНЕШНИЙ</ТипФайла>
<ПрограммаПодготовкиДанных><НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы><Версия>02</Версия></ПрограммаПодготовкиДанных>
<НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
<Версия>02</Версия>
<ИсточникДанных>Р</ИсточникДанных>
*/

идетичное самому XML. тоесть каждую ноду на одной строчке
7 авг 15, 16:37    [17990186]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31983
Ту4а
Необходимо вернуть из процедуры не типом XML. а построчно в виде результирующего селекта
Другими словами вернуть построчно всё дерево (хорошо бы с Identity строки)
Вы бы пример привели, что вам нужно.

В XML нету строк, есть ноды, "элементы дерева". Вот вам ваш запрос и вернул все элементы дерева, всё, что можно назвать словом "элемент", независимо от уровня вложенности.

Более того, уже при присваивании select @x =... сервер удаляет ваши переводы строк, их там нету, в переменной.
7 авг 15, 17:05    [17990338]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
Ту4а
Member

Откуда:
Сообщений: 5
Надо "разкверинодить" @x чтобы вернулось
<Root>
<ИмяФайла>94104.XML</ИмяФайла>
<ЗаголовокФайла>
<ВерсияФормата>07</ВерсияФормата>
<ТипФайла>ВНЕШНИЙ</ТипФайла>
<ПрограммаПодготовкиДанных>
<НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
<Версия>02</Версия>
</ПрограммаПодготовкиДанных>
<ИсточникДанных>Р</ИсточникДанных>
</ЗаголовокФайла>
</Root>

Которое после конверта rows в варчар вернется в датасет клиенту , который не понимает поля типа BLOB xml чтобы потом сохранить построчно в текст. Через булкопи с сервера прав юзеру нет к папкам сервера чтобы соханить хмл в файл.
7 авг 15, 21:10    [17991382]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Берете любую функцию разбиения строки на подстроки по разделителю:
declare @x xml = N'<Root>
    <ИмяФайла>94104.XML</ИмяФайла>
    <ЗаголовокФайла>
        <ВерсияФормата>07</ВерсияФормата>
        <ТипФайла>ВНЕШНИЙ</ТипФайла>
        <ПрограммаПодготовкиДанных>
            <НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
            <Версия>02</Версия>
        </ПрограммаПодготовкиДанных>
        <ИсточникДанных>Р</ИсточникДанных>
    </ЗаголовокФайла>
    <!--...и так далее -->
</Root>';

select
 case when left(a.Value, 1) <> N'<' then N'<' else N'' end + a.Value + N'>'
from
 fnSplitString(cast(@x as nvarchar(max)), N'><') a
order by
 a.ValueOrder;
7 авг 15, 21:47    [17991515]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Исправляем ошибки
select
 case when left(a.Value, 1) <> N'<' then N'<' else N'' end +
 a.Value +
 case when right(a.Value, 1) <> N'>' then N'>' else N'' end
from
 tools.clrfnWT_RegexpSplit(cast(@x as nvarchar(max)), N'><', default) a
order by
 a.ValueOrder;
7 авг 15, 22:06    [17991578]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
Ту4а
Member

Откуда:
Сообщений: 5
Тоесть решение. Конверт всего хмл в varchar(max) а потом бить на строки по закрывающему тегу?
На 2005 сервере загонится ли 10 мегов хмлтекста в варчар?
Вопрос был - помочь научится работать с xquery. Функция nodes() возвращает noderefы узлов, потом с помощью функцмм query() получаются елементы ноды-узла обрамленного тегами xmlтипа, которые могут сконвертится в варчар. Вопрос как с CROSS APPLY ть ,тоесть написать запрос, чтобы перебрать все элементы аналогичные текстовому представлению. Полно примеров как скроссэплить и получит дочерние узлы или все узлы братья. А вот как получить текстовый аналог? Блин пятницавечерпиво. Сам понимаю что пишу то что не могу изложиьть словами. Вообщем через конверт хмл в текст не катит.
7 авг 15, 22:59    [17991706]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Ту4а
На 2005 сервере загонится ли 10 мегов хмлтекста в варчар?
А почитать документацию по varchar(max) не?
Ту4а
Вопрос как с CROSS APPLY ть ,тоесть написать запрос, чтобы перебрать все элементы аналогичные текстовому представлению.
Нет таких элементов. Читайте что такое XQuery.
7 авг 15, 23:41    [17991791]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
Ту4а
Member

Откуда:
Сообщений: 5
Спасибо, благодаря вашему посылу, я теперь знаю что (max) это 2 в 31 степени
Просто до этого 8кило (есл честно писал 4000 -экономил) на варчар хватало с исбытком, а тут файл больше.
Ноо, если есть технология вернуть строки хмл по набору нодерефов, то почемубы не спросить, если своей головы не хватает

По поводу примеров с кросс апли, например почти подходит
http://beyondrelational.com/modules/2/blogs/28/posts/10304/xquery-lab-23-retrieving-values-and-position-of-elements.aspx
А решения нет. Вообщем нужен опыт чтообы написать рекурсию от оня до самого мелкого чилда
8 авг 15, 22:00    [17993926]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Ту4а,

Если мучает жажда знаний и хочется поупираться с XQuery, то вот вам для затравки:
declare @x xml = N'<Root>
    <ИмяФайла SomeAttribute = "SomeValue">94104.XML</ИмяФайла>
    <ЗаголовокФайла>
        <ВерсияФормата>07</ВерсияФормата>
        <ТипФайла>ВНЕШНИЙ</ТипФайла>
        <ПрограммаПодготовкиДанных>
            <НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
            <Версия>02</Версия>
        </ПрограммаПодготовкиДанных>
        <ИсточникДанных>Р</ИсточникДанных>
    </ЗаголовокФайла>
    <!--...и так далее -->
</Root>';

-- dbo.Numbers (n int primary key) - таблица натуральных чисел
with s as
(
 select
  t.n.value('local-name(.)', 'varchar(100)') as Element,
  t.n.query('./*') as Content,
  t.n.value('(./text())[1]', 'varchar(max)') as [Text]
 from
  (select @x.query('count(/*)').value('.', 'int')) a(c) join
  dbo.Numbers n on n.n >= 1 and n.n <= a.c cross apply
  @x.nodes('/*[position() = sql:column("n.n")]') t(n)

 union all

 select
  t.n.value('local-name(.)', 'varchar(100)'),
  t.n.query('./*'),
  t.n.value('(./text())[1]', 'varchar(max)')
 from
  s cross apply
  (select s.Content.query('count(/*)').value('.', 'int')) a(c) join
  dbo.Numbers n on n.n >= 1 and n.n <= a.c cross apply
  s.Content.nodes('/*[position() = sql:column("n.n")]') t(n)
 where
  a.c > 0
)
select * from s;


А можете получить структуру вашего xml-я в формате edge table:
declare @h int;
exec sp_xml_preparedocument @h output, @x;

select * from openxml(@h, '/', 0);

exec sp_xml_removedocument @h;
8 авг 15, 23:56    [17994296]     Ответить | Цитировать Сообщить модератору
 Re: Xml.nodes() вернуть XML построчно на клиента, результирующим запросом  [new]
Ту4а
Member

Откуда:
Сообщений: 5
тыдым... Задача вылежалась и решение пришло само

DECLARE @x xml , @m varchar(max)
select @x ='
<Root>
    <ИмяФайла>94104.XML</ИмяФайла>
    <ЗаголовокФайла>
        <ВерсияФормата>07</ВерсияФормата>
        <ТипФайла>ВНЕШНИЙ</ТипФайла>
        <ПрограммаПодготовкиДанных>
            <НазваниеПрограммы>ВЫГРУЗКА</НазваниеПрограммы>
            <Версия>02</Версия>
        </ПрограммаПодготовкиДанных>
        <ИсточникДанных>Р</ИсточникДанных>
    </ЗаголовокФайла>
    <!--...и так далее -->
</Root>
'

select @m = convert(varchar(max),@x)
Select @m = Replace(@m,'>','&gt;')  -- для наглядности следующие 4 строки не в одну строку записаны
Select @m = Replace(@m,'</','&amp;')
Select @m = Replace(@m,'<','&lt;')
-- вставляю псевдоузлы с психоделическим именем XmL_StRiNg между концом и началом тега ><
Select @x = '<XmL_StRiNg>'+Replace(@m,'&gt;&lt;',+'&gt;</XmL_StRiNg><XmL_StRiNg>&lt;')+'</XmL_StRiNg>'

Select replace(y.value('.','varchar(255)'),'&','</')
  from @x.nodes('XmL_StRiNg') t(y)
26 авг 15, 10:15    [18068717]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить