【问题标题】:Issue in parsing XML in SQL Server在 SQL Server 中解析 XML 的问题
【发布时间】:2023-03-17 13:48:01
【问题描述】:

我是在 SQL Server 中处理 XML 数据的新手。我遇到了一篇文章 (https://www.mssqltips.com/sqlservertip/2899/importing-and-processing-data-from-xml-files-into-sql-server-tables/) 并尝试根据我的 XML 进行修改,但我没有得到任何输出或错误。我不知道如何进一步进行,任何帮助表示赞赏。我提供了以下示例:

    DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)

SELECT @XML = '<DataSet xmlns="http://www.example.com/">
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <NewDataSet xmlns="">
      <General_x0020_Report diffgr:id="General Report1" msdata:rowOrder="0">
        <Device_x0020_No>224610</Device_x0020_No>
        <License_x0020_Plate>AAA 123</License_x0020_Plate>
        <Driver>Driver Name</Driver>
        <Date_x002F_Time>2018-01-01T12:46:04+03:00</Date_x002F_Time>
      </General_x0020_Report>
     </NewDataSet>
  </diffgr:diffgram>
</DataSet>'

EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT Device_x0020_No, License_x0020_Plate, Driver, Date_x002F_Time
FROM OPENXML(@hDoc, 'DataSet/diffgr/NewDataSet/General_x0020_Report')
WITH 
(
Device_x0020_No [varchar](50) 'Device_x0020_No',
License_x0020_Plate [varchar](100) 'License_x0020_Plate',
Driver [varchar](100) 'Driver',
Date_x002F_Time [varchar](100) 'Date_x002F_Time'
)


EXEC sp_xml_removedocument @hDoc
GO

编辑 1:我发现问题在于“diffgr:diffgram”,但不确定如何解决此查询中的命名空间问题

【问题讨论】:

    标签: xml sql-server-2008 tsql xpath xquery


    【解决方案1】:

    FROM OPENXML 与相应的 SP 准备和删除文档已过时,不应再使用。而是使用适当的methods the XML data type provides

    您的 XML 在第一行定义默认命名空间,并使用 &lt;NewDataSet&gt; 将默认命名空间重新定义为空。这意味着,所有&lt;NewDataSet&gt; 下的节点都不存在于任何命名空间中。

    DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
    
    SELECT @XML = '<DataSet xmlns="http://www.example.com/">
      <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
        <NewDataSet xmlns="">
          <General_x0020_Report diffgr:id="General Report1" msdata:rowOrder="0">
            <Device_x0020_No>224610</Device_x0020_No>
            <License_x0020_Plate>AAA 123</License_x0020_Plate>
            <Driver>Driver Name</Driver>
            <Date_x002F_Time>2018-01-01T12:46:04+03:00</Date_x002F_Time>
          </General_x0020_Report>
         </NewDataSet>
      </diffgr:diffgram>
    </DataSet>';
    

    --简单的方法是使用// 进行深度搜索,直接跳转到感兴趣的节点:

    SELECT @XML.value(N'(//Device_x0020_No)[1]',N'nvarchar(max)') AS DeviceNo
          ,@XML.value(N'(//License_x0020_Plate)[1]',N'nvarchar(max)') AS LicensePlate
          ,@XML.value(N'(//Driver)[1]',N'nvarchar(max)') AS Driver
          ,@XML.value(N'(//Date_x002F_Time)[1]',N'datetime') AS [DateTime];
    

    注意DateTime 显示为当地时间(不确定,测试一下)

    更新

    DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
    
    SELECT @XML = '<DataSet xmlns="http://www.example.com/">
      <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
        <NewDataSet xmlns="">
          <General_x0020_Report diffgr:id="General Report1" msdata:rowOrder="0">
            <Device_x0020_No>224610</Device_x0020_No>
            <License_x0020_Plate>AAA 123</License_x0020_Plate>
            <Driver>Driver Name</Driver>
            <Date_x002F_Time>2018-01-01T12:46:04+03:00</Date_x002F_Time>
          </General_x0020_Report>
          <General_x0020_Report diffgr:id="General Report1" msdata:rowOrder="0">
            <Device_x0020_No>2222</Device_x0020_No>
            <License_x0020_Plate>Some other</License_x0020_Plate>
            <Driver>One more</Driver>
            <Date_x002F_Time>2018-01-01T12:46:04+03:00</Date_x002F_Time>
          </General_x0020_Report>
         </NewDataSet>
      </diffgr:diffgram>
    </DataSet>';
    --The easy approach is the deep search with //, jumping right into the nodes of interest:
    
    SELECT r.value(N'(Device_x0020_No)[1]',N'nvarchar(max)') AS DeviceNo
          ,r.value(N'(License_x0020_Plate)[1]',N'nvarchar(max)') AS LicensePlate
          ,r.value(N'(Driver)[1]',N'nvarchar(max)') AS Driver
          ,r.value(N'(Date_x002F_Time)[1]',N'datetime') AS [DateTime]
    FROM @XML.nodes(N'//General_x0020_Report') AS A(r);
    

    【讨论】:

    • 谢谢!您能否让我知道如何从 XML 中获取所有值(例如,驱动程序)而不是硬编码 1
    • 为了保持 XML 代码简单,我只提供了 1 个示例数据。实际上,我们有接近 500 个这样的值(500 组 General_x0020_Report)
    • 我想如果我能得到 1 个节点的解决方案,我可以对整个 XML 做同样的事情,因此我把这个问题提早了。感谢您为我指明正确的方向!我现在是查询 XML 数据和学习的新手。您的解决方案帮助了我。
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 2013-01-18
    相关资源
    最近更新 更多