如何使用FOR XML PATH避免子节点中的命名空间?

Gui*_*len 8 t-sql namespaces for-xml-path

我想直接从数据库创建一个站点地图xml文件(包括图像),而不需要其他进程(如转换或其他技巧).

我的查询是:

;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
Run Code Online (Sandbox Code Playgroud)

返回:

<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>
Run Code Online (Sandbox Code Playgroud)

但我需要这个输出,没有重复的名称空间声明:

<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>
Run Code Online (Sandbox Code Playgroud)

Chr*_*son 4

我确信您意识到额外的多余命名空间声明不会改变 XML 文档的含义,因此如果结果将由符合 XML 的工具使用,那么它们应该无关紧要。尽管如此,我知道有一些工具不能正确处理 XML 命名空间,并且在大型 XML 实例中,多余的重复命名空间声明可能会使结果的大小显着增大,这可能会导致其自身的问题。

一般来说,在 SQL Server 直至 SQL Server 2012 的所有支持 XML 的版本中,前缀SELECT...FOR XML范围内的每个语句WITH XMLNAMESPACES都将在其结果集中的最外层 XML 元素上生成命名空间声明,这是无法回避的事实。

SELECT在您的特定示例中,您可以通过分隔s 而不是嵌套它们并使用ROOT封装根元素的语法来非常接近所需的 XML ,因此:

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 
Run Code Online (Sandbox Code Playgroud)

结果是:

<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>
Run Code Online (Sandbox Code Playgroud)

但这种方法并没有为问题提供完全通用的解决方案。