2012-10-10 53 views
7

Quiero crear un archivo xml de sitemap (incluidas las imágenes) directamente desde la base de datos sin otro proceso (como transformación u otro truco).Cómo evitar el espacio de nombres en los nodos secundarios utilizando FOR XML PATH?

Mi consulta es:

;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 

Devuelve:

<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> 

pero necesito esta salida, sin repetida declaración de espacio de nombres:

<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

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

+0

Posible duplicado de [¿Cómo elimino el espacio de nombres redundante en la consulta anidada al usar FOR XML PATH] (http://stackoverflow.com/questions/3242070/how-do-i- remove-redundant-namespace-in-nested-query-when-using-for-xml-path) – Gabrielius

Respuesta

2

Estoy seguro de que te das cuenta de que la las declaraciones de espacio de nombres otiose adicionales no cambian el significado del documento XML, por lo que si el resultado va a b consumidos por una herramienta conforme a XML, no deberían importar. Sin embargo, sé que hay algunas herramientas que no hacen Espacios de nombres XML correctamente, y en una instancia XML grande, las declaraciones superfluas de espacios de nombres repetidos pueden inflar el tamaño del resultado de manera significativa, lo que puede causar sus propios problemas.

En general, no hay que reconocer el hecho de que cada SELECT...FOR XML declaración dentro del ámbito de un prefijo WITH XMLNAMESPACES generará declaraciones de espacio de nombres en el elemento (s) XML exterior en su conjunto de resultados, en todas las versiones XML de soporte de SQL Server hasta SQL Server 2012.

En el ejemplo específico, puede obtener bastante cerca del XML deseada mediante la separación de los SELECT s en lugar de anidación, y utilizando la sintaxis ROOT para el elemento raíz envolvente, por lo tanto:

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 

El resultado es:

<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> 

Pero este enfoque no proporciona una solución completamente general al problema.

1

Puede usar UDF. Ejemplo:

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') 

Resultado:

<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> 
Cuestiones relacionadas