使用具有多个子节点的多个父节点通过OpenXML解析XML

时间:2016-02-17 16:53:47

标签: sql xml openxml

我有以下XML:

<Report>
    <Accounts>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>45555</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>502</PaymentCode>
              <PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
            </PaymentData>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>50000</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
    </Accounts>
</Report>

我的SQL代码使用以下代码解析它:

SELECT  
            [currCode]  AS [Currency], 
            [AccountBalance] AS [AccountBalance],
            [PaymentCode] AS [PaymentCode],
            [PaymentCurrCode] AS [PaymentCurrCode],
            [PaymentAmount] AS [PaymentAmount]
        FROM OPENXML(@hDoc, 'Report/Accounts/Account',2)
            WITH 
            (
                [currCode] [nchar](3) 'currCode',
                [AccountBalance] [decimal](18, 0) 'AccountBalance',

                [PaymentCode] [nchar](10) 'Payments/PaymentData/PaymentCode',
                [PaymentCurrCode] [nchar](3) 'Payments/PaymentData/PaymentAmount/@currCode',
                [PaymentAmount] [decimal](18, 0) 'Payments/PaymentData/PaymentAmount'
            )

我得到以下结果:

currCode | AccountBalance | PaymentCode | PaymentCurrCode | PaymentAmount
————————————————————————————————————————————————————————————————————————————————
USD      | 45555          | 502         |   GBP           |7000.00000000
USD      | 50000          | 501         |   USD           |5000.00000000

我正在尝试使用相同的openXml查询获取多个paymentdata和多个帐户。如何获得具有以下结果的所有数据:

currCode | AccountBalance | PaymentCode | PaymentCurrCode | PaymentAmount
————————————————————————————————————————————————————————————————————————————————
USD      | 45555          | 502         |   GBP           |7000.00000000
USD      | 45555          | 501         |   USD           |5000.00000000
USD      | 50000          | 501         |   USD           |5000.00000000

2 个答案:

答案 0 :(得分:1)

这应该适合你:

DECLARE @XML XML=
'<Report>
    <Accounts>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>45555</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>502</PaymentCode>
              <PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
            </PaymentData>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>50000</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
    </Accounts>
</Report>';

DECLARE @hDoc INT;
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML; 

SELECT  
            [currCode]  AS [Currency], 
            [AccountBalance] AS [AccountBalance],
            [PaymentCode] AS [PaymentCode],
            [PaymentCurrCode] AS [PaymentCurrCode],
            [PaymentAmount] AS [PaymentAmount]
        FROM OPENXML(@hDoc, 'Report/Accounts/Account/Payments/PaymentData',2)
            WITH 
            (
                [currCode] [nchar](3) '../../Currency',
                [AccountBalance] [decimal](18, 0) '../../AccountBalance',

                [PaymentCode] [nchar](10) 'PaymentCode',
                [PaymentCurrCode] [nchar](3) 'PaymentAmount/@currCode',
                [PaymentAmount] [decimal](18, 0) 'PaymentAmount'
            )
EXEC sp_xml_removedocument @hDoc; 

答案 1 :(得分:1)

这是一种采用XQuery / XPath方法的最新和最先进的方法。结果是相同的,只是更快更好阅读:

DECLARE @XML XML=
'<Report>
    <Accounts>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>45555</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>502</PaymentCode>
              <PaymentAmount currCode="GBP">7000.00000000</PaymentAmount>
            </PaymentData>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
        <Account>
          <Currency>USD</Currency>
          <AccountBalance>50000</AccountBalance>
          <Payments>
            <PaymentData>
              <PaymentCode>501</PaymentCode>
              <PaymentAmount currCode="USD">5000.00000000</PaymentAmount>
            </PaymentData>
          </Payments>
        </Account>
    </Accounts>
</Report>';

SELECT Payment.value('(../../Currency)[1]','nchar(3)') AS currCode
      ,Payment.value('(../../AccountBalance)[1]','decimal(18,0)') AS AccountBalance
      ,Payment.value('PaymentCode[1]','nchar(10)') AS PaymentCode
      ,Payment.value('PaymentAmount[1]/@currCode','nchar(3)') AS PaymentCurrCode
      ,Payment.value('PaymentAmount[1]','decimal(18,0)') AS PaymentCurrCode
FROM @XML.nodes('Report/Accounts/Account/Payments/PaymentData') AS One(Payment)