2012-10-10 7 views
7

Voglio creare un file xml Sitemap (comprese le immagini) direttamente dal database senza un altro processo (come la trasformazione o un altro trucco).Come evitare lo spazio dei nomi nei nodi figlio utilizzando FOR XML PATH?

La mia domanda è:

;WITH XMLNAMESPACES(
    DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9', 
    'http://www.google.com/schemas/sitemap-image/1.1' as [image]) 
SELECT 
    (SELECT    
     'mysite' as [loc], 
     (select 
      'anotherloc' 
      as [image:loc] 
     for XML path('image:image'), type 
     ) 
    for xml path('url'), type 
) 
for xml path('urlset'), type 

Returns:

<urlset xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    <url xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    <loc>mysite</loc> 
    <image:image xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
     <image:loc>anotherloc</image:loc> 
    </image:image> 
    </url> 
</urlset> 

ma ho bisogno di questa uscita, senza dichiarazione dello spazio dei nomi ripetuto:

<urlset xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    <url> 
    <loc>mysite</loc> 
    <image:image> 
     <image:loc>anotherloc</image:loc> 
    </image:image> 
    </url> 
</urlset> 
+0

correlati [sulla DBA] (http://dba.stackexchange.com/questions/23624/how-to-remove-xmlns-from-child-elements -with-for-xml/23697 # 23697) –

+0

Possibile duplicato di [Come rimuovere lo spazio dei nomi ridondante nella query nidificata quando si utilizza FOR XML PATH] (http://stackoverflow.com/questions/3242070/how-do-i- rimuovere ridondante-namespace-in-nested-query-when-using-per-xML-path) – Gabrielius

risposta

2

Sono sicuro ti rendi conto che il ulteriori dichiarazioni di namespace otiose non cambiano il significato del documento XML, quindi se il risultato sta per b E consumati da uno strumento conforme a XML, non dovrebbero avere importanza. Ciononostante, so che ci sono alcuni strumenti là fuori che non eseguono correttamente XML Namespaces, e in una grande istanza XML dichiarazioni di namespace ripetute superflue possono ingigantire la dimensione del risultato in modo significativo, il che potrebbe causare i suoi problemi.

In generale non c'è niente da fare intorno al fatto che ogni SELECT...FOR XML affermazione nell'ambito di un prefisso WITH XMLNAMESPACES genererà dichiarazioni di namespace sull'elemento XML più esterno (s) nel suo set di risultati, in tutte le versioni XML di supporto di SQL Server fino a SQL Server 2012.

Nel tuo esempio specifico, è possibile ottenere abbastanza vicino al XML desiderata separando i SELECT s invece di nidificazione, e utilizzando la sintassi ROOT per l'elemento radice avvolgente, in tal modo:

DECLARE @inner XML; 
WITH XMLNAMESPACES('http://www.google.com/schemas/sitemap-image/1.1' as [image]) 
SELECT @inner = 
( 
    SELECT  
     'anotherloc' AS [image:loc] 
    FOR XML PATH('image:image'), TYPE 
) 

;WITH XMLNAMESPACES( 
    DEFAULT 'http://www.sitemaps.org/schemas/sitemap/0.9' 
) 
SELECT    
     'mysite' AS [loc], 
     @inner 
FOR XML PATH('url'), ROOT('urlset'), TYPE 

Il risultato è:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
    <url> 
    <loc>mysite</loc> 
    <image:image xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns=""> 
     <image:loc>anotherloc</image:loc> 
    </image:image> 
    </url> 
</urlset> 

Ma questo approccio non fornisce una soluzione completamente generale al problema.

1

È possibile utilizzare UDF. Esempio:

ALTER FUNCTION [dbo].[udf_get_child_section] (
    @serviceHeaderId INT 
) 
RETURNS XML 



BEGIN 

    DECLARE @result XML; 

    SELECT @result = 
    (
     SELECT 1 AS 'ChildElement' 
     FOR XML PATH('Child') 
    ) 

    RETURN @result 

END 


GO 

DECLARE @Ids TABLE 
( 
    ID int 
) 

INSERT INTO @Ids 
SELECT 1 AS ID 
UNION ALL 
SELECT 2 AS ID 

;WITH XMLNAMESPACES (DEFAULT 'http://www...com/content') 
SELECT 
    [dbo].[udf_get_child_section](ID) 
FROM 
    @Ids 
FOR XML PATH('Parent') 

Risultato:

<Parent xmlns="http://www...com/content"> 
    <Child xmlns=""> 
    <ChildElement>1</ChildElement> 
    </Child> 
</Parent> 
<Parent xmlns="http://www...com/content"> 
    <Child xmlns=""> 
    <ChildElement>1</ChildElement> 
    </Child> 
</Parent> 
Problemi correlati