Сервер SQL змінює структуру XML, коли вставляється


15

Я вставляю деякі XML-дані в стовпчик XML на SQL-сервер, але після введення даних він був змінений сервером sql. Ось дані, які я вставляю

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />

Коли я читаю його назад, це виглядає приблизно так

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />

Зверніть увагу на другий рядок. Це проблема, тому що вона змінює, яким буде вихід XSLT перетворення. Перший приклад створить простір між даними та прізвищем, а другий не створить простору, тому він буде схожий на ДжонДжонсена, тоді як перший буде схожий на Джон Джонсен.

Чи є якийсь спосіб вирішити це?


Це проблема, оскільки це змінює те, яким буде вихід трансформації XSLT. Перший рядок створить простір між іменем та прізвищем, а другий не створить пробілу між ними, тому він буде схожий на ДжонДжонсена, а перший - як Джон Джонсен
Містер Зак

hmhm, належний простір це "", але не просто пробіл, як у цьому коментарі (ви не можете його побачити)
a_vlad

1
Можливо, ви можете використовувати контрольний символ, який не існує в даних (наприклад, _або ~), а потім замінити його пробілом у часі презентації.
Аарон Бертран

Відповіді:


25

Ви можете використовувати xml:space = "preserve"на вузлах, де потрібно зберегти простір. Використання xml: простір є "лише сигналом про наміри", але SQL-сервер тут нам добрий.

Для одного вузла

declare @X xml =
'<root>
  <element xml:space = "preserve"> </element>
  <element> </element>
</root>'

select @X;

Результат:

<root>
  <element xml:space="preserve"> </element>
  <element />
</root>

Весь документ:

declare @X xml =
'<root xml:space = "preserve">
  <element> </element>
  <element> </element>
</root>'

select @X;

Результат:

<root xml:space="preserve">
  <element> </element>
  <element> </element>
</root>

Іншим варіантом для всього документа є використання перетворення зі стилем 1 .

Збережіть незначний простір білого кольору. Цей параметр стилю встановлює обробку простору xml: простір, щоб відповідати поведінці xml: space = "зберегти".

declare @X xml = convert(xml, 
'<root>
  <element> </element>
  <element> </element>
</root>', 1)

select @X;

Цікаво, що це потрібно. Це не повинно бути компетенцією SQL Server вирішувати, який пробіл "незначний", і мовчки знімати його без змін документів!
Гонки легкості з Монікою

3
@LightnessRacesinOrbit Я дуже задоволений реалізацією SQL Server. Форматування (пробіл) у XML не вважається важливим, поки ви не скажете, що це є. Подивіться на цей приклад, щоб побачити кількість вузлів, які є в документі, і що це стосується розміру пам’яті ..
Mikael Eriksson

3
Я вважаю це специфічним порушенням, оскільки тут дані приймаються як XML і зберігаються як XML, без жодних маніпуляцій чи перетворень чи будь-яких інших форм шенаніганів рівня XML, крім простого зберігання документа (нібито), тому поведінка повинна підпадають під "процесор", а не в "додаток", і тому не повинні позбавляти пробілів .
Гонки легкості з Монікою

9

На цій сторінці документації на SQL Server написано

Дані зберігаються у внутрішньому поданні, яке ... може не бути ідентичною копією тексту XML, оскільки така інформація не зберігається: незначні пробіли, порядок атрибутів, префікси простору імен та декларація XML.

Для вашого прикладу я вважаю, що він вважає, що пробіл середнього тегу не є значним, і тому вільний для рефакторації представлення. Я не думаю, що для цього є виправлення; саме SQL Server реалізує тип даних XML.

Як говорить @Aaron, робочі напрямки включатимуть використання замісника замість білого простору. Споживач повинен пам’ятати, що потрібно вставити та викреслити ці жетони. Крім того, визначте стовпець як nvarchar замість XML. Це, безумовно, збереже весь простір та будь-яке інше форматування. Швидкий приклад:

create table x(i nvarchar(99), j xml);
insert x values ('<a> </a>', '<a> </a>');  -- note the space
select * from x

i           j
----------  -------
<a> </a>    <a />  

Стовпчик nvarchar зберігає вхідний формат, стовпець XML - ні.

Ви втратите можливість використовувати XPATH в SQL-запитах. Якщо XML розбивається лише в додатку, це не має значення. Далі рядок символів можна стиснути, заощаджуючи простір у БД, якщо це важливо для вас.


Напевно, ви все ще можете використовувати XPATH у запитах проти версії XML, навіть якщо ви просто дозволите її переформатувати, доки ви не покладаєтесь на хіт (або пропустіть) незначний простір там.
Аарон Бертран

0

Ви можете обернути свій простір всередині, CDATAзберігаючи дані:

<xsl:text><![CDATA[ ]]></xsl:text>

Здається, що SQL-сервер потім зберігає простір всередині, але видаляє непотрібну CDATAрозмітку при поверненні результату за допомогою SELECT. На щастя, простір зберігається при повторному використанні результату такого SELECT:

DECLARE @X XML = '<text><![CDATA[ ]]></text>'
DECLARE @Y XML

SET @Y = (SELECT @X)

SELECT @Y

Результатом буде:

<text> </text>

Також спробував CDATA, але його також видалили.
Містер Зах

@MrZach CDATA сама видаляється, але простір залишається. (Пробували в SQL Express 2016.)
Бруно

Дивно, тут простір прибрали. Подумайте також про експрес 2016 або 2017 року
пан Зах
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.