使用 t-sql 从 XML 文档中提取数据

Extract data from XML document using t-sql

我一直在尝试在 sql 服务器 2019 上使用 t-sql 从以下 xml 文档中提取数据。

XML:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>https://www.URL1.com/1</loc>
    <image:image>
      <image:loc>https://www.URL1.com/11</image:loc>
    </image:image>
    <image:image>
      <image:loc>https://www.URL1.com/12</image:loc>
    </image:image>
    <image:image>
      <image:loc>https://www.URL1.com/13</image:loc>
    </image:image>
  </url>
  <url>
    <loc>https://www.URL1.com/2</loc>
    <image:image>
      <image:loc>https://www.URL1.com/21</image:loc>
    </image:image>
    <image:image>
      <image:loc>https://www.URL1.com/22</image:loc>
    </image:image>
  </url>
  <url>
    <loc>https://www.URL1.com/3</loc>
    <image:image>
      <image:loc>https://www.URL1.com/32</image:loc>
    </image:image>
  </url>
</urlset>

我想从 xml 文档中提取数据到 SQL 服务器 table。我想要的输出如下

期望的输出:

+------------------------+-------------------------+
|          Loc           |        ImageLoc         |
+------------------------+-------------------------+
| https://www.URL1.com/1 | https://www.URL1.com/11 |
| https://www.URL1.com/1 | https://www.URL1.com/12 |
| https://www.URL1.com/1 | https://www.URL1.com/13 |
| https://www.URL1.com/2 | https://www.URL1.com/21 |
| https://www.URL1.com/2 | https://www.URL1.com/22 |
| https://www.URL1.com/3 | https://www.URL1.com/32 |
+------------------------+-------------------------+

到目前为止,我的尝试都惨遭失败。我尝试了很多东西,但唯一能让我获得 Loc 元素的是以下内容,我尝试使用 OUTER APPLY/CROSS APPLY 来获取 ImageLoc,但没有成功。

我的尝试:

DECLARE @xml XML
SELECT @xml = BulkColumn
FROM OPENROWSET(BULK 'M:\Files\MyXML.xml', SINGLE_BLOB) x

SELECT
    t.c.value('(text())[1]', 'VARCHAR(max)') URLs
,   t2.i.value('(text())[1]', 'VARCHAR(max)') URLs

FROM @xml.nodes('*:urlset/*:url/*:loc') t(c)
OUTER APPLY  @xml.nodes('*:urlset/*:url/*:loc/*:image/*:loc') t2(i)

你能帮忙吗?提前致谢

此答案由 lptr 在评论中作为 link 对 fiddle 发布。正如 OP 所说,它回答了他们的问题,而 lptr 没有 wish/respond 发布答案,我已将其迁移到答案部分。

这里他们使用 * 通配符而不是定义命名空间来从 XML:

中获取值

dbfiddle.uk/...

SELECT
    t.c.value('(*:loc/text())[1]', 'VARCHAR(max)') URLs
,   t2.i.value('(text())[1]', 'VARCHAR(max)') URLs

FROM @xml.nodes('*:urlset/*:url') t(c)
OUTER APPLY  t.c.nodes('*:image/*:loc') t2(i);

您还需要在 SQL 中定义您的命名空间。这可以通过将 WITH XMLNAMESPACES 放在查询的开头并在那里定义来完成。然后你可以定义 image 命名空间并在你的引用中加上前缀,return 来自节点的值:

WITH XMLNAMESPACES ('xyz' AS image)
SELECT u.i.value('(../loc/text())[1]','varchar(500)') AS loc,
       u.i.value('(image:loc/text())[1]','varchar(500)') AS loc
FROM @xml.nodes('urlset/url/image:image') u(i);

db<>fiddle