【问题标题】:Querying XML data types which have xmlns node attributes查询具有 xmlns 节点属性的 XML 数据类型
【发布时间】:2013-05-09 12:31:10
【问题描述】:

我有以下 SQL 查询:

DECLARE @XMLDOC XML
SET @XMLDOC = '<Feed><Product><Name>Foo</Name></Product></Feed>'

SELECT  x.u.value('Name[1]', 'varchar(100)') as Name
from @XMLDOC.nodes('/Feed/Product') x(u)

这会返回:

Name
----
Foo

但是,如果我的 &lt;Feed&gt; 节点有一个 xmlns 属性,那么这不会返回任何结果:

DECLARE @XMLDOC XML
SET @XMLDOC = '<Feed xmlns="bar"><Product><Name>Foo</Name></Product></Feed>'

SELECT  x.u.value('Name[1]', 'varchar(100)') as Name
from @XMLDOC.nodes('/Feed/Product') x(u)

返回:

Name
----

只有当我有 xmlns 属性时才会发生这种情况,其他任何东西都可以正常工作。

为什么会这样,如何修改我的 SQL 查询以返回结果而不考虑属性?

【问题讨论】:

    标签: sql sql-server xml sql-server-2008 xml-namespaces


    【解决方案1】:

    如果您的 XML 文档具有 XML 名称空间,那么您需要在查询中考虑这些名称!

    因此,如果您的 XML 看起来像您的示例,那么您需要:

    -- define the default XML namespace to use
    ;WITH XMLNAMESPACES(DEFAULT 'bar')
    SELECT   
        x.u.value('Name[1]', 'varchar(100)') as Name
    from 
        @XMLDOC.nodes('/Feed/Product') x(u)
    

    或者,如果您希望明确控制要使用的 XML 命名空间(例如,如果您有多个),请使用 XML 命名空间前缀:

    -- define the XML namespace 
    ;WITH XMLNAMESPACES('bar' as b)
    SELECT   
        x.u.value('b:Name[1]', 'varchar(100)') as Name
    from 
        @XMLDOC.nodes('/b:Feed/b:Product') x(u)
    

    【讨论】:

    • +1 有没有办法简单地忽略 xmlns?我很想将XML 数据类型转换为字符串,去掉 xmlns 属性,然后将其转换回来......
    • 我真的不关心命名空间,而且这是在 xmlns URL 上带有版本控制的第三方提要,因此容易发生外部更改
    • @Curt:不,当 XML 命名空间存在于您的 XML 中时,您不能简单地忽略它——您需要处理它。如果您只有一个 XML 命名空间 - 使用方法 #1 将其定义为默认 XML 命名空间,并且使用起来应该相当简单直接
    • 命名空间可能会改变。这是一个外部 XML 提要,它在 XMLNS 的 URL 中具有版本控制。有没有办法从 XML 中获取 XMLNS 值,以便我可以确保它始终相同?
    • @Curt:我认为没有任何内置功能。您必须对 XML 进行文本解析才能找到 XML 命名空间
    【解决方案2】:

    除了XMLNAMESPACES 解决方案,您还可以使用笨重的local-name 语法...

    DECLARE @XMLDOC XML
    SET @XMLDOC = '<Feed xmlns="bar"><Product><Name>Foo</Name></Product></Feed>'
    
    SELECT  x.u.value('*[local-name() = "Name"][1]', 'varchar(100)') as Name
    from @XMLDOC.nodes('/*[local-name() = "Feed"]/*[local-name() = "Product"]') x(u)
    

    【讨论】:

    • +1 感谢您提供替代解决方案。除了可怕之外,这对性能很重要吗?
    • 我想是的!与专门针对给定命名空间的XMLNAMESPACES 解决方案不同,它确实具有不关心命名空间的优点(或可能是缺点?:))。
    • 除此之外 - 我发现 SQLServer 中的 XML 解析非常慢......也许我做错了!
    • 谢谢,因为这个解决方案很可能不是最佳实践,我没有将它标记为答案,但会在迫切需要的时候参考它! :)
    【解决方案3】:

    你可以define namespaces点赞:

    WITH    XMLNAMESPACES ('bar' as b)
    SELECT  x.u.value('b:Name[1]', 'varchar(100)') as Name
    FROM    @XMLDOC.nodes('/b:Feed/b:Product') x(u)
    

    【讨论】:

      猜你喜欢
      • 2011-01-09
      • 2021-07-27
      • 1970-01-01
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-31
      • 1970-01-01
      相关资源
      最近更新 更多