Используйте API-интерфейсы SQL Server 2005 XML для нормализации фрагмента XML - PullRequest
3 голосов
/ 21 июля 2011

У меня есть некоторый (нетипизированный) XML, хранящийся в SQL Server 2005, который мне нужно преобразовать в нормализованную структуру. Структура документа в настоящее время выглядит так:

<wrapper>
 <parent />
 <node />
 <node />
 <node />

 <parent />
 <node />
 <node />
 <node />
<wrapper> 

Я хочу преобразовать его так:

<wrapper>
 <parent>
  <node />
  <node />
  <node />
 </parent>
 <parent>
  <node />
  <node />
  <node />
 </parent>
<wrapper> 

Я могу выбрать XML в реляционную структуру, если мне нужно, поставив проблему в том, что нет атрибутов, связывающих родительский и дочерний узлы вместе, поэтому порядок становится проблемой при использовании операций на основе множеств. Как я могу использовать .nodes () /. Value () / другие API-интерфейсы SQL Server XML для преобразования этих данных? Преобразование должно выполняться как часть пакетного сценария SQL, поэтому его извлечение на другой инструмент / язык не является разумным вариантом для меня.

1 Ответ

1 голос
/ 22 июля 2011

На самом деле - следующий код работает (группировка здесь может быть не очень оптимальной, но в любом случае):

declare @xml xml = '
    <wrapper>
     <parent id="1" />
     <node id="1" />
     <node id="2" />
     <node id="3" />

     <parent id="2" />
     <node id="4" />
     <node id="5" />
     <node id="6" />
    </wrapper> 
'

;with px as
(
    select row_number() over (order by (select 1)) as RowNumber
        ,t.v.value('@id', 'int') as Id
        ,t.v.value('local-name(.)', 'nvarchar(max)') as TagName
    from @xml.nodes('//wrapper/*') as t(v)
)
select p.Id as [@id],
    (
        select n.Id as id
        from px n
        where n.TagName = 'node'
            and n.RowNumber > p.RowNumber
            and not exists
            (
                select null
                from px np
                where np.TagName = 'parent'
                    and np.RowNumber > p.RowNumber
                    and np.RowNumber < n.RowNumber
            )
        order by n.RowNumber
        for xml raw('node'), type
    )
from px p
where p.TagName = 'parent'
order by p.RowNumber
for xml path('parent'), root('wrapper')

Но я не рекомендую его использовать. См. Здесь: http://msdn.microsoft.com/en-us/library/ms172038%28v=sql.90%29.aspx:

В SQLXML 4.0 порядок документов не всегда определяется
Поэтому я не уверен, что мы можем положиться на порядок тегов внутри оболочки (и приведенный выше код - скорее просто для развлечения, чем для практического использования).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...