SQL Server создает пространство имен XML, если указано значение по умолчанию

Вот простой пример:

declare @myXml xml
set @myXML = '
<root>
    <line id="1"/>
    <line id="2"/>
    <line id="3"/>
</root>'
select t.c.query('.')
from @myXml.nodes('/root/line') t(c)

Как и ожидалось, я возвращаю три строки, которые выглядят так:

<line id="1" />

Однако, когда XML объявляет свое пространство имен (даже просто xmlns по умолчанию), вам также необходимо указать это пространство имен в SQL, иначе ваш набор результатов окажется пустым. Я знаю два способа: оператор declare в вызове метода nodes () или оператор с xmlnamespaces. Воспользуемся последним:

declare @myXml xml
set @myXML = '
<root xmlns="urn:somename">
    <line id="1"/>
    <line id="2"/>
    <line id="3"/>
</root>';

with xmlnamespaces(default 'urn:somename')
select t.c.query('.')
from @myXml.nodes('/root/line') t(c)

Хотя сейчас я получаю результаты, в них есть определенная странность. Указанное пространство имен добавляется как «p1» вместо значения по умолчанию. Итак, мой результат выглядит так:

<p1:line xmlns:p1="urn:somename" id="1" />

В этой статье Technet, раздел B. Объявление пространства имен по умолчанию показывает, чего я пытаюсь достичь, но я получаю результат, показанный в D. Создание с использованием пространств имен по умолчанию. Поскольку мой пример не очень похож на последний, я не понимаю, почему я получаю эти префиксы.

Обновление: для полноты изложения это дает точно такой же симптом, что и синтаксис with xmlnamespaces:

select t.c.query('.')
from @myXml.nodes('declare default element namespace "urn:somename";/root/line') t(c)

person Cobus Kruger    schedule 28.10.2013    source источник
comment
Я думаю, вам нужно будет объявить пространство имен элемента по умолчанию в вашем операторе XQuery, как это предлагается в статье в B.   -  person wst    schedule 28.10.2013
comment
@wst У меня точно такой же симптом, независимо от того, использую ли я синтаксис xmlnamespaces или оператор declare.   -  person Cobus Kruger    schedule 28.10.2013
comment
Вы пытались объявить пространство имен по умолчанию в своем операторе select?   -  person wst    schedule 28.10.2013
comment
@wst В операторе select? Я не понимаю, что вы имеете в виду. Я пробовал использовать как синтаксис с xmlnamespaces, показанный выше, так и добавление объявления в вызове nodes (), и они доставляют идентичные результаты.   -  person Cobus Kruger    schedule 29.10.2013
comment
С точки зрения того, какие данные содержит этот фрагмент XML, <p1:line xmlns:p1="urn:somename" id="1" /> и <p1 id="1" /> внутри пространства имен по умолчанию urn:somename содержат в точности одни и те же данные. Беспокойство о точном формате строки обычно является признаком нестабильности в другом месте (например, какой-либо другой фрагмент кода, использующий ручной синтаксический анализ, а не использование соответствующей библиотеки XML)   -  person Damien_The_Unbeliever    schedule 29.10.2013
comment
@Damien_The_Unbeliever Абсолютно да. Однако, когда вы не контролируете код, который будет анализировать XML, лучше не отклоняться от опубликованной спецификации, с которой получатель работал довольно долгое время, и я не хочу усложнять ситуацию, доставляя данные в другом формате. формат от того, что было нужно. Это все больше и больше похоже на то, что мне придется выполнять обработку вне SQL.   -  person Cobus Kruger    schedule 29.10.2013
comment
См. Мой пример ниже. Я тестировал в SSMS, и он возвращает правильный результат.   -  person wst    schedule 31.10.2013


Ответы (1)


Объявите пространство имен элемента по умолчанию в select при первоначальном запросе XML, и все элементы будут использовать объявление пространства имен по умолчанию вместо префикса:

declare @myXml xml
set @myXML = '
<root xmlns="urn:somename">
    <line id="1"/>
    <line id="2"/>
    <line id="3"/>
</root>';    
with xmlnamespaces(default 'urn:somename')
select t.c.query('
  declare default element namespace "urn:somename";
  .')
from @myXml.nodes('/root/line') t(c)

=>

<line xmlns="urn:somename" id="1" />
<line xmlns="urn:somename" id="2" />
<line xmlns="urn:somename" id="3" />
person wst    schedule 29.10.2013