2009-09-15 11 views
6

C'è un modo per ottenere un ritorno XML di SQL Server utilizzare CDATA? Ho XML viene restituito da SQL Server in questo modo:SQL Server XML output con CDATA

<locations> 
    <site id="124"> 
     <sitename>Texas A &amp; M</sitename> 
    </site> 
</locations> 

Quando sono tenuti ad avere questo:

<locations> 
    <site id="124"> 
     <sitename><![CDATA[Texas A & M]]></sitename> 
    </site> 
</locations> 
+3

Sembra un requisito strano: devono entrambi venire alla stessa cosa in qualsiasi pars xml conforme agli standard ER. Ma poi, i clienti saranno clienti. –

+0

Sfortunatamente, il post-processo non è un'opzione, dato che SQL ha già preso i dati delle colonne (Texas A & M) e li ha fatti sfuggire per XML (Texas A & M) diretto. Qualcosa che CDATA consente. Il client non vuole analizzare l'XML, quindi cercare e riscrivere i valori. E ho scoperto rapidamente che restituire XML, piuttosto che prendere una query di ritorno e costruire la stringa XML a mano, è la preferenza definitiva. –

risposta

14

Vedere le opzioni di FOR XML EXPLICIT (parametro Direttiva). Fornisce il maggior grado di controllo e puoi anche specificare CDATA. Ecco a good tutorial.

E il codice addapted da quel tutorial:

declare @agent table 
( 
    AgentID int, 
    Fname varchar(5), 
    SSN varchar(11) 
) 

insert into @agent 
select 1, 'Vimal', '123-23-4521' union all 
select 2, 'Jacob', '321-52-4562' union all 
select 3, 'Tom', '252-52-4563' 

SELECT 
    1 AS Tag, 
    NULL AS Parent, 
    NULL AS 'Agents!1!', 
    NULL AS 'Agent!2!AgentID', 
    NULL AS 'Agent!2!Fname!Element', 
    NULL AS 'Agent!2!SSN!cdata' 
UNION ALL 
SELECT 
    2 AS Tag, 
    1 AS Parent, 
    NULL, 
    AgentID, 
    Fname, 
    SSN 
FROM @agent 
FOR XML EXPLICIT 
+0

Questo era giusto per i soldi. Grazie per l'aiuto. –

+1

Attenzione, tuttavia, che se si inserisce questo output in una variabile XML T-SQL o in un campo XML, il CDATA verrà convertito nel formato con e commerciale e non può essere disattivato. http://stackoverflow.com/a/9133622/864696 –

0

Come Joel menzionato nel commento di cui sopra, queste due forme dovrebbe significare esattamente la stessa cosa . Tuttavia, se il modulo CDATA è realmente richiesto, è possibile scrivere un postprocessore che prende il primo modulo come input e emette il secondo modulo utilizzando CDATA.

In questo caso, un postprocessore avrebbe unencode i dati con escape XML nel primo modulo e ricodificarlo utilizzando un metodo compatibile con CDATA. Vedere la domanda Is there a way to escape a CDATA end token in xml? per considerazioni sull'esclusione di CDATA.

0

Ecco un esempio del mio modo di ottenere CDATA:

DECLARE @GlobalDateFormat varchar(32) 
SET @GlobalDateFormat = 'MM/dd/yyyy hh:mm tt' 

DECLARE @xml XML 

SET @xml = 
(
    SELECT 
      SegmentId   = ISNULL(SegmentId,0) 
     , DocumentId  = ISNULL(DocumentId,0) 
     , Title    = CAST(Core.dbo.fCharFormat('xmlCDATA',Title,DEFAULT,'') AS xml) 
     , DocumentShortName = CAST(Core.dbo.fCharFormat('xmlCDATA',DocumentShortName,DEFAULT,'') AS xml) 
     , [FileName]  = CAST(Core.dbo.fCharFormat('xmlCDATA',[FileName],DEFAULT,'') AS xml) 
     , [Path]   = CAST(Core.dbo.fCharFormat('xmlCDATA',[Path],DEFAULT,'') AS xml) 
     , CreateDate  = ISNULL(Core.dbo.fDateFormat(@GlobalDateFormat,CreateDate),Core.dbo.fDateFormat(@GlobalDateFormat,GETDATE())) 
     , ModificationDate = ISNULL(Core.dbo.fDateFormat(@GlobalDateFormat,ModificationDate),Core.dbo.fDateFormat(@GlobalDateFormat,GETDATE())) 
     , TemplateId  = ISNULL(CAST(TemplateId AS varchar(16)),'') 
     , IsRoot   = ISNULL(IsRoot,0) 
     , IsActive   = ISNULL(IsActive,0) 
     , SortOrdinal  = ISNULL(CAST(SortOrdinal AS varchar(16)),'') 
     , ClientId   = ISNULL(ClientId,'') 
     , Tag    = CAST(Core.dbo.fCharFormat('xmlCDATA',Tag,DEFAULT,'') AS xml) 
     FROM 
      Document 
     WHERE 
      DocumentId = 9073 
     FOR XML AUTO, ELEMENTS 
) 

SELECT @xml 

Ecco il dettaglio rilevante dal mio donnola-like, CDATA- funzione di manipolazione:

IF @cmdName = 'xmlCDATA' 
BEGIN 
    IF @chars IS NULL 
    BEGIN 
     SET @charsOut = @charsDefault 
    END 
    ELSE 
    BEGIN 
     SET @chars = REPLACE(@chars,'<![CDATA[','') 
     SET @chars = REPLACE(@chars,']]>','') 
     SET @charsOut = '<![CDATA[' + @chars + ']]>' 
    END 
END 
+0

Questo fallirà se qualcuno dei tuoi dati, ad es. Titolo, contiene la stringa ']]>'. –

+0

Ouch! Destra! Dovrò scrivere una funzione dedicata esclusivamente a CDATA ... dovrebbe averla entro la fine del giorno ... – rasx

+0

Aspetta un attimo 'Greg, ho appena provato questo in Management Studio: SELECT CAST (' 'AS xml) Hai provato questo? Che succede? – rasx