无法使用外部应用解析 XML

Can't parse XML with outer apply

我在 table 中有一个 XML 列,我试图从中解析出值到扁平 table 结构。

我正在尝试在此处输入 XML,但 Whosebug 将其视为代码,当我尝试将其格式化为代码时,它仍然不接受它。

我什至无法从“Header”级别获取数据。

<RequestMessage xmlns="http://iec.ch/TC57/2011/schema/message" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Message.xsd">
  <Header>
    <Verb>created</Verb>
    <Noun>MeterReadings</Noun>
    <Timestamp>2021-03-08T00:57:18+01:00</Timestamp>
    <Source>Ipsum Lorum</Source>
    <AsyncReplyFlag>true</AsyncReplyFlag>
    <AckRequired>true</AckRequired>
    <MessageID>Ipsum Lorum</MessageID>
    <CorrelationID />
  </Header>
  <Payload>
    <MeterReadings xmlns:MeterReadings="http://iec.ch/TC57/2011/MeterReadings#" xmlns="http://iec.ch/TC57/2011/MeterReadings#">
      <MeterReading>
        <IntervalBlocks>
          <IntervalReadings>
            <timeStamp>2021-03-07T01:00:00+01:00</timeStamp>
            <value>480.196</value>
            <ReadingQualities>
              <ReadingQualityType ref="3.0.0" />
            </ReadingQualities>
          </IntervalReadings>
          <IntervalReadings>
            <ReadingType ref="11.0.7.3.1.2.12.1.1.0.0.0.0.101.0.3.72.0" />
          </IntervalReadings>
        </IntervalBlocks>
        <Meter>
          <mRID>0000000000000</mRID>
          <status>
            <remark>Ipsum Lorum</remark>
            <value>ESP</value>
          </status>
        </Meter>
        <UsagePoint>
          <mRID>73599900000000</mRID>
        </UsagePoint>
      </MeterReading>
    </MeterReadings>
  </Payload>
</RequestMessage>

我无法解析它,我尝试使用其他线程中的示例。我试图不使用 OPENXML 解决方案,因为需要 DECLARE 并执行内置程序以定期从内存中清除 XML。我正在尝试使用 OUTER APPLY 解决方案。 喜欢 How to parse XML data in SQL server table or .

中的 Shugos 解决方案

没用。

它 returns 时间戳列为空。

select 
t.file_created_time
,c.value('(Timestamp)[1]','varchar(max)') as timestamp
from load.t t
OUTER APPLY t.xml_data.nodes('RequestMessage/Header') as m(c)

您需要在 XQuery 的 XML 文档中尊重并包含​​ XML 命名空间

<RequestMessage xmlns="http://iec.ch/TC57/2011/schema/message"
                **********************************************

尝试这样的事情:

WITH XMLNAMESPACES(DEFAULT N'http://iec.ch/TC57/2011/schema/message')
SELECT
    t.id,
    c.value('(Timestamp)[1]','varchar(max)') as timestamp
FROM
    load.t t
CROSS APPLY
    t.xml_data.nodes('RequestMessage/Header') AS m(c)

另外,在我的 SQL 服务器上尝试 运行 时,我得到一个错误,显示的 XML 格式不正确......

更新:

如果您还需要访问 Payload 部分中的位 - 您还需要遵守那里的 that XML 命名空间:

<MeterReadings xmlns:MeterReadings="http://iec.ch/TC57/2011/MeterReadings#"
               xmlns="http://iec.ch/TC57/2011/MeterReadings#">
               ***********************************************

试试这个:

WITH XMLNAMESPACES(N'http://iec.ch/TC57/2011/schema/message' as hdr,
                   N'http://iec.ch/TC57/2011/MeterReadings#' as mr)
SELECT
    t.id,
    c.value('(hdr:Timestamp)[1]', 'varchar(50)') AS timestamp,
    col.value('(mr:MeterReading/mr:IntervalBlocks/mr:IntervalReadings/mr:timeStamp)[1]', 'varchar(50)') AS MeterReadingsTimestamp
FROM
    load.t t
CROSS APPLY
    t.xml_data.nodes('/hdr:RequestMessage/hdr:Header') AS m(c)
CROSS APPLY
    t.xml_data.nodes('/hdr:RequestMessage/hdr:Payload/mr:MeterReadings') AS mr(col)

请尝试以下解决方案。

从SQLServer 2005开始,在处理XML数据类型时,最好使用基于w3c标准的XQuery语言。

Microsoft 专有 OPENXML 及其伙伴 sp_xml_preparedocumentsp_xml_removedocument 的保留只是为了与过时的 SQL Server 2000 向后兼容。它们的使用减少到非常多少数边缘案例。

我不得不注释掉以下标签 <!--<IntervalReadings>--> 以使您的 XML 格式正确。

XML Header 片段有一个默认命名空间:

  • xmlns="http://iec.ch/TC57/2011/schema/message"

XML Payload 片段有自己的两个附加命名空间:

  • xmlns:MeterReadings="http://iec.ch/TC57/2011/MeterReadings#"
  • xmlns="http://iec.ch/TC57/2011/MeterReadings#"

应考虑命名空间。

在下面查看。

SQL

DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xml_data XML);
INSERT INTO @tbl (xml_data) VALUES
(N'<RequestMessage xmlns="http://iec.ch/TC57/2011/schema/message"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:noNamespaceSchemaLocation="Message.xsd">
    <Header>
        <Verb>created</Verb>
        <Noun>MeterReadings</Noun>
        <Timestamp>2021-03-08T00:57:18+01:00</Timestamp>
        <Source>Ipsum Lorum</Source>
        <AsyncReplyFlag>true</AsyncReplyFlag>
        <AckRequired>true</AckRequired>
        <MessageID>Ipsum Lorum</MessageID>
        <CorrelationID/>
    </Header>
    <Payload>
        <MeterReadings xmlns:MeterReadings="http://iec.ch/TC57/2011/MeterReadings#"
                       xmlns="http://iec.ch/TC57/2011/MeterReadings#">
            <MeterReading>
                <IntervalBlocks>
                    <IntervalReadings>
                        <timeStamp>2021-03-07T01:00:00+01:00</timeStamp>
                        <value>480.196</value>
                        <ReadingQualities>
                            <ReadingQualityType ref="3.0.0"/>
                        </ReadingQualities>
                    </IntervalReadings>
                    <!--<IntervalReadings>-->
                    <ReadingType ref="11.0.7.3.1.2.12.1.1.0.0.0.0.101.0.3.72.0"/>
                </IntervalBlocks>
                <Meter>
                    <mRID>0000000000000</mRID>
                    <status>
                        <remark>Ipsum Lorum</remark>
                        <value>ESP</value>
                    </status>
                </Meter>
                <UsagePoint>
                    <mRID>73599900000000</mRID>
                </UsagePoint>
            </MeterReading>
        </MeterReadings>
    </Payload>
</RequestMessage>');
-- DDL and sample data population, end

WITH XMLNAMESPACES(DEFAULT 'http://iec.ch/TC57/2011/schema/message')
SELECT id
    , c.value('(Noun/text())[1]','VARCHAR(30)') AS Noun
    , c.value('(Timestamp/text())[1]','DATETIMEOFFSET(0)') AS [timestamp]
FROM @tbl
    CROSS APPLY xml_data.nodes('/RequestMessage/Header') AS t(c);

输出

+----+---------------+----------------------------+
| id |     Noun      |         timestamp          |
+----+---------------+----------------------------+
|  1 | MeterReadings | 2021-03-08 00:57:18 +01:00 |
+----+---------------+----------------------------+