XML数据转SQL表,获取子节点数据困难

问题描述 投票:0回答:1

我有一个要加载到 SQL 中的 xml 文件。我可以毫无问题地加载 xml 文件并将顶级节点放入 sql 表中。我很难到达下一级子节点。

这是一个示例 xml 文件(类似于我试图进入表格的内容):

    <RSR:ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:RSR="urn:rsrNamespace" xsi:schemaLocation="urn:rsrNamespace SomeSchema.xsd">
      <ClientReport>
        <ClientID>05929</ClientID>
        <ClientFirstName>Eric</ClientFirstName>
        <ClientLastName>Jones</ClientLastName>
        <ClientService>
          <ClientServices>
            <ServiceID>250</ServiceID>
            <Salesperson>Charlie</Salesperson>
            <Cost>15.95</Cost>
          </ClientServices>
          <ClientServices>
            <ServiceID>356</ServiceID>
            <Salesperson>Jane</Salesperson>
            <Cost>34.25</Cost>
          </ClientServices>
        </ClientService>
      </ClientReport>
    </RSR:ROOT>

我可以毫无问题地将顶级节点 ClientID 和 ClientName 放入表中。我可以运行此 sql 并将值存入临时表 CLIENTREPORT:

CREATE TABLE ##XMLTable (XMLData XML)

SET @cmd = 'INSERT INTO ##XMLTable SELECT CONVERT(XML, BulkColumn) AS Bulkcolumn FROM OPENROWSET (BULK ''' + @FullPathName + ''', SINGLE_BLOB) as X'

SET @cmd = 'WITH XMLNAMESPACES (''urn:rsrNamespace'' AS p) 
INSERT INTO ##CLIENTREPORT (ClientID, ClientFullName)
SELECT
    CLIENTDATA.ClientReport.value(''(./ClientID)[1]'', ''VARCHAR(100)''),
    CLIENTDATA.ClientReport.value(''(./ClientFirstName)[1]'', ''VARCHAR(100)'') + '' '' + CLIENTDATA.ClientReport.value(''(./ClientLastName)[1]'', ''VARCHAR(100)'')
FROM ##XMLTable X
    CROSS APPLY X.XMLData.nodes(''p:ROOT/ClientReport'') AS CLIENTDATA (ClientReport)'

我在访问那些较低级别的节点时遇到问题 - ServiceID、Salesperson、Cost。这是我所拥有的不起作用的东西:

SET @cmd = 'WITH XMLNAMESPACES (''urn:rsrNamespace'' AS p) 
INSERT INTO ##CLIENTREPORTSERVICES (ClientID, Salesperson)
SELECT
    CLIENTDATA.ClientReport.value(''(./ClientID)[1]'', ''VARCHAR(100)''),
    CLIENTSERVICEDATA.ClientServices.value(''(./Salesperson)[1]'', ''VARCHAR(25)'')
FROM ##XMLTable X
    CROSS APPLY X.XMLData.nodes(''p:ROOT/ClientReport'') AS CLIENTDATA (ClientReport)
    CROSS APPLY CLIENTDATA.ClientReport.nodes(''ClientService/ClientServices'') AS CLIENTSERVICEDATA (ClientServices)'

我得到的只是 Salesperson 字段中的空值。关于 XQuery 和导航到较低级别的节点,我缺少什么?

xml xquery xquery-sql openrowset
1个回答
0
投票

请尝试以下操作。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (XMLData XML);
INSERT @tbl (XMLData) VALUES
(N'<QSR:ROOT xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:QSR="urn:qsrNamespace" xsi:schemaLocation="urn:qsrNamespace SomeSchema.xsd">
    <ClientReport>
        <ClientID>05929</ClientID>
        <ClientFirstName>Eric</ClientFirstName>
        <ClientLastName>Jones</ClientLastName>
        <ClientService>
            <ClientServices>
                <ServiceID>250</ServiceID>
                <Salesperson>Charlie</Salesperson>
                <Cost>15.95</Cost>
            </ClientServices>
            <ClientServices>
                <ServiceID>356</ServiceID>
                <Salesperson>Jane</Salesperson>
                <Cost>34.25</Cost>
            </ClientServices>
        </ClientService>
    </ClientReport>
</QSR:ROOT>');
-- DDL and sample data population, end

;WITH XMLNAMESPACES ('urn:qsrNamespace' AS QSR)
SELECT c.value('(ClientID/text())[1]', 'VARCHAR(20)') AS ClientID
    , c.value('(ClientFirstName/text())[1]', 'VARCHAR(20)') AS ClientFirstName
    , c.value('(ClientLastName/text())[1]', 'VARCHAR(20)') AS ClientLastName
FROM @tbl
CROSS APPLY XMLData.nodes('/QSR:ROOT/ClientReport') AS t(c);

;WITH XMLNAMESPACES ('urn:qsrNamespace' AS QSR)
SELECT p.value('(ClientID/text())[1]', 'VARCHAR(20)') AS ClientID
    , c.value('(ServiceID/text())[1]', 'VARCHAR(20)') AS ServiceID
    , c.value('(Salesperson/text())[1]', 'VARCHAR(20)') AS Salesperson
    , c.value('(Cost/text())[1]', 'DECIMAL(10,2)') AS Cost
FROM @tbl
CROSS APPLY XMLData.nodes('/QSR:ROOT/ClientReport') AS t1(p)
CROSS APPLY p.nodes('ClientService/ClientServices') AS t2(c);

输出#1

客户ID 客户名字 客户姓氏
05929 埃里克 琼斯

输出#2

客户ID 服务编号 营业员 费用
05929 250 查理 15.95
05929 356 34.25
© www.soinside.com 2019 - 2024. All rights reserved.