SQL Server FOR XML PATH: установите xml-декларацию или инструкцию по обработке xml-stylesheet сверху

Я хочу установить инструкцию обработки, чтобы включить таблицу стилей поверх XML:

Та же проблема была с объявлением xml (например, <?xml version="1.0" encoding="utf-8"?>)

Желаемый результат:

<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<TestPath>
  <Test>Test</Test>
  <SomeMore>SomeMore</SomeMore>
</TestPath>

Мои исследования привели меня к синтаксису node test и processing-instruction().

Этот

SELECT 'type="text/xsl" href="stylesheet.xsl"' AS [processing-instruction(xml-stylesheet)]
      ,'Test' AS Test
      ,'SomeMore' AS SomeMore
FOR XML PATH('TestPath')

производит это:

<TestPath>
  <?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
  <Test>Test</Test>
  <SomeMore>SomeMore</SomeMore>
</TestPath>

Все подсказки, которые я нашел, говорят мне преобразовать XML в VARCHAR, объединить его «вручную» и преобразовать обратно в XML. Но это - как сказать - некрасиво?

Это работает очевидно:

SELECT CAST(
'<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
<TestPath>
  <Test>Test</Test>
  <SomeMore>SomeMore</SomeMore>
</TestPath>' AS XML);

Есть ли шанс решить это?


person Shnugo    schedule 19.11.2015    source источник


Ответы (2)


Есть еще один способ, для которого потребуется два шага, но вам не нужно обрабатывать XML как строку в любом месте процесса:

declare @result XML =
(
    SELECT 
        'Test' AS Test,
        'SomeMore' AS SomeMore
    FOR XML PATH('TestPath')
)
set @result.modify('
    insert <?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>
    before /*[1]
')

Sqlfiddle Demo

Выражение XQuery, переданное функции modify(), сообщает SQL Server, что нужно вставить узел инструкций по обработке перед корневым элементом XML.

ОБНОВЛЕНИЕ:

Нашел другую альтернативу, основанную на следующем потоке: объединить два фрагмента xml в один? < /а> . Я лично предпочитаю этот способ:

SELECT CONVERT(XML, '<?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?>'),
(
    SELECT 
        'Test' AS Test,
        'SomeMore' AS SomeMore
    FOR XML PATH('TestPath')
)
FOR XML PATH('')

Sqlfiddle Demo

person har07    schedule 21.11.2015
comment
Отличный вклад, спасибо! Пока они не найдут что-то вроде top-processing-instruction(), это очень хорошая работа! - person Shnugo; 21.11.2015
comment
Привет har07, мне как раз нужно было добавить xml-декларацию и я подумал, что можно было бы сделать аналогично, но не получилось. Я добавил ответ с (довольно очевидным) решением... - person Shnugo; 27.05.2016

Как выяснилось, отличный ответ har07 не работает с XML-декларацией. Единственный способ, который я мог найти, был следующим:

DECLARE @ExistingXML XML=
(
    SELECT 
        'Test' AS Test,
        'SomeMore' AS SomeMore
    FOR XML PATH('TestPath'),TYPE
);

DECLARE @XmlWithDeclaration NVARCHAR(MAX)=
(
    SELECT N'<?xml version="1.0" encoding="UTF-8"?>'
           +
           CAST(@ExistingXml AS NVARCHAR(MAX))
);
SELECT @XmlWithDeclaration;

Вы должны оставаться в строке string после этого шага, любое преобразование в настоящий XML либо выдаст ошибку (если кодировка отличается от UTF-16), либо это объявление xml будет пропущено.

person Shnugo    schedule 27.05.2016