【问题标题】:How to avoid namespace in child nodes using FOR XML PATH?如何使用 FOR XML PATH 避免子节点中的命名空间?
【发布时间】:2012-10-10 15:56:49
【问题描述】:

我想直接从数据库创建站点地图 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

返回:

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

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

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

【问题讨论】:

标签: tsql namespaces for-xml-path


【解决方案1】:

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

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

在您的具体示例中,您可以通过分隔 SELECTs 而不是嵌套它们,并使用 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 

结果是:

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

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

【讨论】:

    【解决方案2】:

    您可以使用 UDF。示例:

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

    结果:

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

    【讨论】:

      【解决方案3】:

      回答可能为时已晚,但这是一个快速的解决方案。

      `DECLARE @PageNumber Int = 1;
      声明@siteMapXml XML;
      ; 使用 XML 命名空间 (
          'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' 作为“schemaLocation”,
          'http://www.w3.org/2001/XMLSchema-instance' 作为 xsi,
          'http://www.google.com/schemas/sitemap-image/1.1' 作为 [图片],
          默认“http://www.sitemaps.org/schemas/sitemap/0.9”
          )
              选择@siteMapXml = (
      
                                          选择
                                             蛞蝓定位,
                                             转换(varchar(300),[图像])作为[图像:图像/图像:位置]
                                             ,
                                             Convert(char(10), UpdatedOnUtc, 126) 作为 lastmod,
                                             'hourly' 作为 changefreq,
                                             '0.5' 优先
                                          FROM 产品(NOLOCK)
                                          其中页码 = @PageNumber
      
      FOR XML PATH ('url'), ROOT ('urlset'))
      SELECT @siteMapXml = REPLACE(CAST(@siteMapXml AS NVARCHAR(MAX)), 'xmlns:schemaLocation=', 'xsi:schemaLocation=')
      选择@siteMapXml`

      【讨论】:

        猜你喜欢
        • 2012-06-20
        • 1970-01-01
        • 2017-03-10
        • 1970-01-01
        • 2020-05-13
        • 2019-05-11
        • 2013-03-16
        • 2016-06-09
        • 2016-02-18
        相关资源
        最近更新 更多