将 XML 节点中的值替换为使用 XQUERY 正确引用节点并过滤所需值

Replacing values in the XML nodes to reference nodes correctly using XQUERY and filter required values

我有一个 table,其中包含 XML 数据,其中一列中有多个节点。类似于下面的内容。

<SendWorkOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                creationDateTime="2021-06-05T10:16:09.713+12:00"
                requestCorrelationId="63cbec24c87a1bfa88999ef373e"
                xmlns="http://mycompany.co.nz/customerservices/servicepartner/workorder">
    <WORKORDERSET>
        <WORKORDER action="Replace">
            <WONUM>123456</WONUM>
            <DESCRIPTION>My work order</DESCRIPTION>
        </WORKORDER>
    </WORKORDERSET>
</SendWorkOrders>

我想将格式更改为如下所示,以便使用 XQUERY 和过滤所需的节点。

<SendWorkOrders>
<WORKORDERSET>
<WORKORDER>
<WONUM>123456</WONUM>
<DESCRIPTION>My work order</DESCRIPTION>
</WORKORDER>
</WORKORDERSET>
</SendWorkOrders>

这里有更多详细信息。

我有一个名为 'WorkOrderLogs' 的 table,它有 4 列 EventId、Source、Timestamp、SendWorkOrders。如第一个代码片段中所述,SendWorkOrders 列存储来自客户的原始 XML。我正在尝试使用下面的查询来引用 XML 值中的特定节点。

SELECT e.EventId,e.Timestamp,e.SendWorkOrder,e.Source,
X.Y.value('(WONUM)[1]','VARCHAR(20)') as WONUMBER,
X.Y.value('(DESCRIPTION)[1]','VARCHAR(256)') as DESCRIPTION
From WorkOrderLogs e
OUTER APPLY e.SendWorkOrders.nodes('SENDWORKORDERS/WORKORDERSET/WORKORDER/WONUM') as X(Y)

它 returns NULL 值作为我的根 node/namespace 包含模式的附加信息和其他细节。所以,我在想,如果我能够将值格式化为简单的东西,那么我就可以在这里实现我想要的。

我设法编写了一个查询来选择节点,但未能正确引用它们。根节点包含每条消息唯一的模式和附加信息。我无法简化它以针对所需的节点。我是 T-SQL 的新手,所以非常感谢任何 help/pointers。

提前致谢。

更新:

非常感谢 Yitzhak Khabinsky。对于一个用例来说,它就像一个魅力。但是,我现在遇到了另一个问题。命名空间存在于子节点中。

示例值是这样的。

<OrderNotification xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <POSKI xmlns="http://MyCompany.co.nz">12345</POSKI>
        <BUKRS xmlns="http://MyCompany.co.nz">ABCD</BUKRS>
        <PRCTR xmlns="http://MyCompany.co.nz">1324</PRCTR>
    </OrderNotification>

我正在尝试的查询是

DECLARE @OrderLogs TABLE ( OrderNotification XML);
INSERT INTO @ProjectLogs (ProjectNotification)
(SELECT Info
      
  FROM [MainLogging].[dbo].[JobLogs]

  where EventId = 'XXXXXXXX'
  and Message ='OrderNotification');

  WITH XMLNAMESPACES (DEFAULT 'http://mycompany.co.nz')
  SELECT c.value('(POSKI/text())[1]','VARCHAR(20)') AS ORDER
    , c.value('(BUKRS/text())[1]','VARCHAR(256)') AS DESCRIPTION
    FROM @ProjectLogs
    CROSS APPLY OrderNotification.nodes('/OrderNotification') AS t(c);

请尝试以下解决方案。

它是一个最小的可重现示例。您按原样将它复制到 SSMS,它就可以工作。

它通过 WITH XMLNAMESPACES 子句处理默认命名空间。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, SendWorkOrders XML);
INSERT INTO @tbl (SendWorkOrders) VALUES
(N'<SendWorkOrders xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                creationDateTime="2021-06-05T10:16:09.713+12:00"
                requestCorrelationId="63cbec24c87a1bfa88999ef373e"
                xmlns="http://mycompany.co.nz/customerservices/servicepartner/workorder">
    <WORKORDERSET>
        <WORKORDER action="Replace">
            <WONUM>123456</WONUM>
            <DESCRIPTION>My work order</DESCRIPTION>
        </WORKORDER>
    </WORKORDERSET>
</SendWorkOrders>');
-- DDL and sample data population, end

WITH XMLNAMESPACES (DEFAULT 'http://mycompany.co.nz/customerservices/servicepartner/workorder')
SELECT ID
    , c.value('(WONUM/text())[1]','VARCHAR(20)') AS WONUMBER
    , c.value('(DESCRIPTION/text())[1]','VARCHAR(256)') AS DESCRIPTION
FROM @tbl
    CROSS APPLY SendWorkOrders.nodes('/SendWorkOrders/WORKORDERSET/WORKORDER') AS t(c);

输出

+----+----------+---------------+
| ID | WONUMBER |  DESCRIPTION  |
+----+----------+---------------+
|  1 |   123456 | My work order |
+----+----------+---------------+