【问题标题】:XML Column - using "with namespace" in an xmlColumn.value()XML Column - 在 xmlColumn.value() 中使用“with namespace”
【发布时间】:2020-06-11 00:27:09
【问题描述】:

我正在尝试创建一个课程来演示命名空间。 我的数据库中有一个 XML 列,其中包含一个 FlyReservations 根,以及多个 FlightReservation 元素。每个 FlightReservation 就像一个“行”,并且有各种我想显示为列的子元素。我可以在不使用命名空间的情况下让它工作,现在我想用命名空间前缀来做。

我这里有一个可重现的样本:

https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=608c9bf89fe6ada200216fde855557c7

这是 T-SQL:

DECLARE @xmlDoc XML = 
 '<ns0:FlightReservations xmlns:ns0="http://SchemaLesson.FlightReservations">
  <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation">
    <DepartureAirportCode>DFW</DepartureAirportCode>"
  </ns1:FlightReservation>
  <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation">
    <DepartureAirportCode>OKC</DepartureAirportCode>"
  </ns1:FlightReservation>
  </ns0:FlightReservations>
'
;

WITH XMLNAMESPACES ('http://SchemaLesson.FlightReservations' as ns0, 
                    'http://SchemaLesson.FlightReservation' as ns1, 
                    DEFAULT 'http://SchemaLesson.FlightReservation'
                    )
select 
    t2.xmlDoc2.query('.') AS result  , 
    t2.xmlDoc2.value('(.//*[local-name()="DepartureAirportCode"])[1]','varchar(5)') AS DepartureAirportCode1, 
    t2.xmlDoc2.value('(./ns1:FlightReservation/DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode2, 
    t2.xmlDoc2.value('(.//ns1:FlightReservation/DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode3, 
    t2.xmlDoc2.value('(.//DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode4, 
    t2.xmlDoc2.value('(.//ns1:DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode5 
    from @xmlDoc.nodes('//ns1:FlightReservation')  AS t2(xmlDoc2) 

from 语句似乎正在工作,因为我得到两行输出,结果列设置为此(使用一个或另一个机场代码):

<ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation">
  <DepartureAirportCode>DFW</DepartureAirportCode>"
</ns1:FlightReservation>

我可以使用 XpathTester.com 单独测试我的 xpath: http://www.xpathtester.com/xpath/3a16744fb05e13264af788bb65210df5

SQL 2019 中显示的结果是:

唯一有效的地方是我使用了 local-name 函数,而我的演示的目的是使用 ns1 前缀。也许我有一个错字,但我一直盯着它并尝试了一段时间,但看不到它。 “with namespace”设置是否也适用于 .value 子句?

Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64) Sep 24 2019 13:48:23 版权所有 (C) 2019 Microsoft Corporation Developer Edition (64-bit) o​​n Windows Server 2019 Standard 10.0 (Build 17763: )

【问题讨论】:

  • 请分享所需的输出。 DepartureAirportCode1 - DepartureAirportCode5 有什么区别?

标签: sql-server xml tsql xquery


【解决方案1】:

请检查下面的 T-SQL。

您的 XML 只有两个命名空间,而不是三个。我调整了.nodes() 方法的XPath 表达式。具有 NULL 值的列在 .value() 方法中具有可疑的 XPath

SQL

DECLARE @xmlDoc XML = 
 '<ns0:FlightReservations xmlns:ns0="http://SchemaLesson.FlightReservations">
  <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation">
    <DepartureAirportCode>DFW</DepartureAirportCode>"
  </ns1:FlightReservation>
  <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation">
    <DepartureAirportCode>OKC</DepartureAirportCode>"
  </ns1:FlightReservation>
  </ns0:FlightReservations>';

WITH XMLNAMESPACES ('http://SchemaLesson.FlightReservations' as ns0
    , 'http://SchemaLesson.FlightReservation' as ns1)
select c.query('.') AS result  , 
    c.value('(.//*[local-name()="DepartureAirportCode"])[1]','varchar(5)') AS DepartureAirportCode1, 
    c.value('(DepartureAirportCode/text())[1]', 'varchar(5)') AS DepartureAirportCode2, 
    c.value('(.//ns1:FlightReservation/DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode3, 
    c.value('(.//DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode4, 
    c.value('(.//ns1:DepartureAirportCode)[1]', 'varchar(5)') AS DepartureAirportCode5 
from @xmlDoc.nodes('/ns0:FlightReservations/ns1:FlightReservation')  AS t(c);

输出

+----------------------------------------------------------------------------------------------------------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+
|                                                           result                                                           | DepartureAirportCode1 | DepartureAirportCode2 | DepartureAirportCode3 | DepartureAirportCode4 | DepartureAirportCode5 |
+----------------------------------------------------------------------------------------------------------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+
| <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation"><DepartureAirportCode>DFW</DepartureAirportCode>" |                       |                       |                       |                       |                       |
|   </ns1:FlightReservation>                                                                                                 | DFW                   | DFW                   | NULL                  | DFW                   | NULL                  |
| <ns1:FlightReservation xmlns:ns1="http://SchemaLesson.FlightReservation"><DepartureAirportCode>OKC</DepartureAirportCode>" |                       |                       |                       |                       |                       |
|   </ns1:FlightReservation>                                                                                                 | OKC                   | OKC                   | NULL                  | OKC                   | NULL                  |
+----------------------------------------------------------------------------------------------------------------------------+-----------------------+-----------------------+-----------------------+-----------------------+-----------------------+

【讨论】:

  • 谢谢。是的,问题在于额外的“默认”命名空间。
  • 我不明白为什么 (DepartureAirportCode/text())[1] 适用于 DepartureAirportCode2。这在 XPath Tester 中对“结果”列中的内容不起作用。为什么不 (./ns1:FlightReservation/DepartureAirportCode)[1]?我以为你必须指定一个“。”在开始使用“cross apply”或“nodes()”的结果时
  • @NealWalters,(1) XPath Tester,我们不知道它背后的引擎是什么。 (2) "." 中不需要,ns1:FlightReservation 中不需要。上下文已经在该元素之下。
猜你喜欢
  • 2012-02-01
  • 2020-07-01
  • 2022-12-31
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多