2012-10-10 13 views
7

Ich möchte eine Sitemap XML-Datei (einschließlich Bilder) direkt aus der Datenbank ohne einen anderen Prozess (wie Transformation oder einen anderen Trick) erstellen.Wie vermeidet man Namespace in Kindknoten mit FOR XML PATH?

Meine Frage ist:

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

Aber ich brauche diese Ausgabe, ohne wiederholte Namespace-Deklaration:

<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

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

+0

Mögliches Duplikat von [Wie entferne ich redundanten Namespace in verschachtelten Abfragen bei Verwendung von FOR XML PATH] (http://stackoverflow.com/questions/3242070/how-do-i- remove-redundant-Namespace-in-geschachtelte-Abfrage-bei-Verwendung-für-XML-Pfad) – Gabrielius

Antwort

2

Ich bin sicher, dass Sie erkennen, dass die Zusätzliche otiose Namespace-Deklarationen ändern die Bedeutung des XML-Dokuments nicht, wenn also das Ergebnis b ist Wenn sie von einem XML-konformen Werkzeug konsumiert werden, sollten sie keine Rolle spielen. Trotzdem weiß ich, dass es einige Tools gibt, die XML-Namespaces nicht korrekt ausführen, und in einer großen XML-Instanz überflüssige wiederholte Namespace-Deklarationen können die Größe des Ergebnisses erheblich aufblähen, was seine eigenen Probleme verursachen kann.

Im Allgemeinen ist keine da um die Tatsache bekommt, dass jede SELECT...FOR XML Aussage im Rahmen eines WITH XMLNAMESPACES Präfix wird Namespace-Deklarationen auf dem äußersten XML-Elemente (e) in seiner Ergebnismenge in allen XML-Unterstützung Versionen von SQL Server erzeugen bis zu SQL Server 2012.

In Ihrem speziellen Beispiel können Sie ziemlich nah an der gewünschten XML erhalten, indem die SELECT s Trennung statt nisten sie, und mit Hilfe der ROOT Syntax für die Kuvertierung Wurzelelement, also:

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 

Das Ergebnis ist:

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

Aber dieser Ansatz bietet keine vollständige allgemeine Lösung für das Problem.

1

Sie können UDF verwenden. Beispiel:

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

Ergebnis:

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