2010-08-14 47 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(或此類)。我的猜測可能不是,第三方應用程序的使用受到嚴格控制。 (對不起,在我原來的問題中沒有提到這個。) – 2010-08-16 19:11:47

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