Получить значения в XML узлах, используя SQL - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть XML в SQL столбце таблицы. Мне нужно декодировать это xml и получить значение конкретных узлов. Найдите мой XML ниже

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns:createTransactionResponse
            xmlns:impl="http://office/work/services/service1"
            xmlns:ns="http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd"
            xmlns:tns="http://www.erdeftq.ae/Activematrix/ESB/service1/1_0">
            <transactionResponse>
                <transaction-info>
                    <registrationId>R1234</registrationId>
                    <trialId>T12345</trialId>
                    <transactionId>12345</transactionId>
                    <transactionDate>27-02-2020:08:47</transactionDate>
                    <status>Confirmed</status>
                </transaction-info>
            </transactionResponse>
        </ns:createTransactionResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Мне нужны значения узлов: registrationId, транзакции и статуса, и я попробовал это, но не смог добиться успеха, так как в результате я получил пустое значение:

DECLARE @xml XML
SET @xml = 'XML here'
SELECT T.C.value('@status', 'nvarchar(100)') FROM @xml.nodes('createTransactionResponse/transactionResponse/transaction-info/status') T(C)
SELECT T.C.value('@trans', 'nvarchar(100)') FROM @xml.nodes('createTransactionResponse/transactionResponse/transaction-info/transactionId') T(C)
SELECT T.C.value('@id', 'nvarchar(100)') FROM @xml.nodes('createTransactionResponse/transactionResponse/transaction-info/registrationId') T(C)

Буду признателен за любую помощь / исправление

Ответы [ 2 ]

2 голосов
/ 27 февраля 2020

Ваша собственная попытка игнорирует пространства имен и не указывает полный XPath.

Попробуйте один из следующих подходов:

Ваш XML:

DECLARE @xml XML
SET @xml = '<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns:createTransactionResponse
            xmlns:impl="http://office/work/services/service1"
            xmlns:ns="http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd"
            xmlns:tns="http://www.erdeftq.ae/Activematrix/ESB/service1/1_0">
            <transactionResponse>
                <transaction-info>
                    <registrationId>R1234</registrationId>
                    <trialId>T12345</trialId>
                    <transactionId>12345</transactionId>
                    <transactionDate>27-02-2020:08:47</transactionDate>
                    <status>Confirmed</status>
                </transaction-info>
            </transactionResponse>
        </ns:createTransactionResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>';

- Это наиболее явный (который всегда лучший способ ):

WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS n1
                  ,'http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd' AS n2)
SELECT @xml.value('(/n1:Envelope/n1:Body/n2:createTransactionResponse/transactionResponse/transaction-info/registrationId/text())[1]','nvarchar(max)') AS RegistrationId
      ,@xml.value('(/n1:Envelope/n1:Body/n2:createTransactionResponse/transactionResponse/transaction-info/transactionId/text())[1]','nvarchar(max)') AS TransactionId
      ,@xml.value('(/n1:Envelope/n1:Body/n2:createTransactionResponse/transactionResponse/transaction-info/status/text())[1]','nvarchar(max)') AS [Status];

- Это позволит избежать повторения XPath, но .nodes() приводит к некоторым накладным расходам:

WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS n1
                  ,'http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd' AS n2)
SELECT ti.value('(registrationId/text())[1]','nvarchar(max)') AS RegistrationId
      ,ti.value('(transactionId/text())[1]','nvarchar(max)') AS TransactionId
      ,ti.value('(status/text())[1]','nvarchar(max)') AS [Status]
FROM @xml.nodes('/n1:Envelope/n1:Body/n2:createTransactionResponse/transactionResponse/transaction-info') A(ti);

- И это для ленивых людей: -)

SELECT @xml.value('(//*:registrationId)[1]','nvarchar(max)') AS RegistrationId
      ,@xml.value('(//*:transactionId)[1]','nvarchar(max)') AS TransactionId
      ,@xml.value('(//*:status)[1]','nvarchar(max)') AS [Status];

Подсказка: последний (для ленивых ) использует глубину поиск //) и использование подстановочного знака для пространства имен. Это очень опасно, если элементы могут встречаться в вашем XML.

несколько раз.
0 голосов
/ 27 февраля 2020

XML у вас довольно сложный. У вас есть несколько пространств имен, причем разные узлы используют разные. Это означает, что вам нужно использовать WITH XMLNAMESPACES, чтобы объявить все это.

Затем вам нужно использовать nodes, чтобы перейти к нужному узлу, добавив им префиксы в соответствующих пространствах имен, пока вы не доберетесь до transaction-info. Затем вы используете value для получения информации.

@Status - это не то, что вам нужно, а то, что у вас есть что-то вроде <node status=1\>, вам нужно получить text() значение узла.

Это приводит к следующему:

DECLARE @X xml = '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns:createTransactionResponse
            xmlns:impl="http://traffic2/traffic/services/service1"
            xmlns:ns="http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd"
            xmlns:tns="http://www.abc.ae/Activematrix/ESB/service1/1_0">
            <transactionResponse>
                <transaction-info>
                    <registrationId>R1234</registrationId>
                    <trialId>T12345</trialId>
                    <transactionId>12345</transactionId>
                    <transactionDate>27-02-2020:08:47</transactionDate>
                    <status>Confirmed</status>
                </transaction-info>
            </transactionResponse>
        </ns:createTransactionResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>';

WITH XMLNAMESPACES ('http://schemas.xmlsoap.org/soap/envelope/' AS [SOAP-ENV],
                    'http://traffic2/traffic/services/service1' AS impl, --YOu don't use this in the XML, but incldued anyway, for completeness
                    'http://www.regfrez.com/schemas/service1_V2/SharedResources/XMLSchema/Schema.xsd' AS ns,
                    'http://www.abc.ae/Activematrix/ESB/service1/1_0' AS tns) --YOu don't use this in the XML, but incldued anyway, for completeness
SELECT ti.value('(status/text())[1]','varchar(10)') AS [Status],
       ti.value('(transactionId/text())[1]','int') AS Trans,
       ti.value('(registrationId/text())[1]','varchar(10)') AS ID
FROM @X.nodes('SOAP-ENV:Envelope/SOAP-ENV:Body/ns:createTransactionResponse/transactionResponse/transaction-info') N(ti);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...