2010-08-14 1 views
0

Я использую SELECT ... FOR XML для генерации XML и он создает именно то, что я хочу видеть - в SSMS. Но ...T-SQL: экспорт таблицы в XML с использованием хранимых процессов - форматирование?

Проблема, с которой я столкнулся, - это экспортированный XML-файл, содержащий весь XML-объект в одной строке. Это правильный XML, но как я могу отформатировать вывод? (один элемент на строку, завершенный с помощью \ r \ n и предпочтительно с отступом). Файл должен быть доступен для чтения в блокноте.

Кроме того, есть ли лучший способ приклеить заголовок XML?

Конечно, я мог бы написать хранимую процедуру CLR для выполнения экспорта, но, похоже, излишний. (Почему это даже трудно?)

ALTER PROCEDURE [dbo].[ExportConfigTablesToXML] 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

--EXEC sp_configure 'show advanced options', 1 
--RECONFIGURE 
--EXEC sp_configure 'xp_cmdshell', 1 
--RECONFIGURE 
--EXEC sp_configure 'show advanced options', 0 
--RECONFIGURE 

DECLARE @FileName VARCHAR(50) 
DECLARE @SQLCmd VARCHAR(500) 
DECLARE @CreateXmlHeader varchar(500) 
DECLARE @AppendXmlBody varchar(500) 
DECLARE @DeleteTempFile varchar(500) 

SELECT @FileName = 'C:\Temp\SampleXMLOutput.xml' 
SELECT @SQLCmd = 'bcp ' + 
    '"SELECT Name AS [@Name], ServiceName, MachineName,' + 
    ' CASE PollInterval WHEN 10 THEN NULL ELSE PollInterval END AS PollInterval,' + 
    ' CASE Alerts WHEN 1 THEN NULL ELSE ''false'' END AS Alerts, ' + 
    ' CASE Pages WHEN 1 THEN NULL ELSE ''false'' END AS Pages' + 
    ' FROM Watchdog.dbo.[Config.Services] [Service]' + 
    ' FOR XML PATH(''Service''), ROOT(''Services'')"' + 
    ' queryout ' + 
    @FileName + '.tmp' + 
    ' -S' + @@SERVERNAME + 
    ' -T -c -r -t' 

SET @CreateXmlHeader = 'ECHO ^<?xml version="1.0" ?^> > ' + @FileName 
SET @AppendXmlBody = 'TYPE ' + @FileName + '.tmp >> ' + @FileName 
SET @DeleteTempFile = 'DEL ' + @FileName + '.tmp' 

EXECUTE master..xp_cmdshell @SQLCmd 
EXECUTE master..xp_cmdshell @CreateXmlHeader 
EXECUTE master..xp_cmdshell @AppendXmlBody 
EXECUTE master..xp_cmdshell @DeleteTempFile 

END 

ответ

0

Поскольку вы работаете команды в любом случае, вы могли бы, возможно:

xmllint --format 

От Free XML Formatting tool

+0

Это приложение предназначено для развертывания в домене производственной сети, и я не знаю, разрешено ли xmllint (или такое). Мое предположение, вероятно, нет, использование сторонних приложений жестко контролируется. (Извините, не упоминал об этом в моем первоначальном вопросе.) –

1

Вы могли бы включать в себя добавление заголовка, помещая извлечение XML в подзапрос. Так что ваша команда BCP становится:

SELECT @SQLCmd = 'bcp ' + 
    '"SELECT ''<?xml version="1.0"?>'' + ' + 
    '(SELECT Name AS [@Name], ServiceName, MachineName,' + 
    ' CASE PollInterval WHEN 10 THEN NULL ELSE PollInterval END AS PollInterval,' + 
    ' CASE Alerts WHEN 1 THEN NULL ELSE ''false'' END AS Alerts, ' + 
    ' CASE Pages WHEN 1 THEN NULL ELSE ''false'' END AS Pages' + 
    ' FROM Watchdog.dbo.[Config.Services] [Service]' + 
    ' FOR XML PATH(''Service''), ROOT(''Services''))"' + 
    ' queryout ' + 
    @FileName + '.tmp' + 
    ' -S' + @@SERVERNAME + 
    ' -T -c -r -t' 
1

Чтобы закрыть петлю, я нашел решение, которое записывает XML один тег в строке с не отступа. Это отвратительный взлом, но это приемлемо для моих целей, давайте посмотрим, проходит ли он проверку кода. Если кто-то хочет посмотреть на файл с отступом, он может открыть его в IE (дважды щелкнув по нему).

Конечно, реальное решение будет храниться в CLR, но на данный момент я предпочитаю, чтобы этот способ упрощал развертывание, т. Е. Просто запускал один SQL-скрипт для развертывания БД.

ALTER PROCEDURE [dbo].[ExportConfigTablesToXML] 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 

--EXEC sp_configure 'show advanced options', 1 
--RECONFIGURE 
--EXEC sp_configure 'xp_cmdshell', 1 
--RECONFIGURE 
--EXEC sp_configure 'show advanced options', 0 
--RECONFIGURE 

DECLARE @FileName VARCHAR(50) 
DECLARE @SQLCmd VARCHAR(1000) 

SELECT @FileName = 'C:\Temp\SampleXMLOutput.xml' 
SELECT @SQLCmd = 'bcp ' + 
    '"DECLARE @xml xml; ' + 
    'DECLARE @text varchar(MAX); ' + 

    'SET @xml = (SELECT Name AS [@Name], ServiceName, MachineName, ' + 
    ' CASE PollInterval WHEN 10 THEN NULL ELSE PollInterval END AS PollInterval, ' + 
    ' CASE Alerts WHEN 1 THEN NULL ELSE ''false'' END AS Alerts, ' + 
    ' CASE Pages WHEN 1 THEN NULL ELSE ''false'' END AS Pages ' + 
    'FROM Watchdog.dbo.[Config.Services] [Service] ' + 
    'FOR XML PATH(''Service''), ROOT(''Services''), TYPE); ' + 

    'SET @text = ''<?xml version=""1.0"" ?>'' + CHAR(13) + CHAR(10); ' + 
    'SET @text = @text + REPLACE(CAST(@xml AS varchar(MAX)), ''><'', ''>'' + CHAR(13) + CHAR(10) + ''<''); ' + 
    'SELECT @text" ' + 

    ' queryout ' + 
    @FileName + 
    ' -S' + @@SERVERNAME + 
    ' -T -c -r -t' 

EXECUTE master..xp_cmdshell @SQLCmd 

END