I want to create a sitemap xml file (including images) directly from the database without another process (like transformation or another trick).
My query is:
;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>
But I need this output, without repeated namespace declaration:
<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>
Name conflicts in XML can easily be avoided using a name prefix. In the example above, there will be no conflict because the two <table> elements have different names.
You can change the default namespace within a particular element by adding an xmlns attribute to the element. Example 4-4 is an XML document that initially sets the default namespace to http://www.w3.org/1999/xhtml for all the XHTML elements. This namespace declaration applies within most of the document.
An XML namespace is a collection of names that can be used as element or attribute names in an XML document. The namespace qualifies element names uniquely on the Web in order to avoid conflicts between elements with the same name.
As defined by the W3C Namespaces in XML Recommendation , an XML namespace is a collection of XML elements and attributes identified by an Internationalized Resource Identifier (IRI); this collection is often referred to as an XML "vocabulary."
I'm sure you realise that the additional otiose namespace declarations don't change the meaning of the XML document, so if the result is going to be consumed by an XML-conformant tool, they shouldn't matter. Nevertheless I know there are some tools out there which don't do XML Namespaces correctly, and in a large XML instance superfluous repeated namespace declarations can bloat the size of the result significantly, which may cause its own problems.
In general there is no getting around the fact that each SELECT...FOR XML
statement within the scope of a WITH XMLNAMESPACES
prefix will generate namespace declarations on the outermost XML element(s) in its result set, in all XML-supporting versions of SQL Server up to SQL Server 2012.
In your specific example, you can get fairly close to the desired XML by separating the SELECT
s rather than nesting them, and using the ROOT
syntax for the enveloping root element, thus:
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
The result being:
<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>
But this approach doesn't provide a completely general solution to the problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With