Question

I need assistance querying into an XML file with repeating data using T-SQL (2008/2012).

The XML code is below. It contains some summary level nodes (VENDOR_NAME, VENDOR_NUMBER, SUBTOTAL) and then detail level rows (in the NONPO container node), and then one further set of detail rows (in the NONPO2 container node).

<Document ID="11">
  <Version>4.7</Version>
  <LastModifiedInVersion>4.7</LastModifiedInVersion>
  <Controls>
    <Control ID="VENDOR_NAME">
      <Value>CVS</Value>
    </Control>
    <Control ID="VENDOR_NUMBER">
      <Value>1101</Value>
    </Control>
  </Controls>
  <Container ID="NONPO">
    <Header />
    <Row>
      <Control ID="INVOICE_NUMBER">
        <Value>23126</Value>
      </Control>
      <Control ID="INVOICE_DATE">
        <Value>05/13/2014</Value>
      </Control>
      <Container ID="NONPO2">
        <Header />
        <Row>
          <Control ID="DESCRIPTION">
            <Value>Pens</Value>
          </Control>
          <Control ID="AMOUNT">
            <Value>50.32</Value>
          </Control>
        </Row>
        <Row>
          <Control ID="DESCRIPTION">
            <Value>Tape</Value>
          </Control>
          <Control ID="AMOUNT">
            <Value>60.00</Value>
          </Control>
        </Row>
        <Footer>
          <Control ID="INV_SUBTOTAL">
            <Value>110.32</Value>
          </Control>
        </Footer>
      </Container>
    </Row>
    <Row>
      <Control ID="INVOICE_NUMBER">
        <Value>61626</Value>
      </Control>
      <Control ID="INVOICE_DATE">
        <Value>06/01/2014</Value>
      </Control>
      <Container ID="NONPO2">
        <Header />
        <Row>
          <Control ID="DESCRIPTION">
            <Value>Microsoft Office</Value>
          </Control>
          <Control ID="AMOUNT">
            <Value>1600.00</Value>
          </Control>
        </Row>
        <Footer>
          <Control ID="INV_SUBTOTAL">
            <Value>1600.00</Value>
          </Control>
        </Footer>
      </Container>
    </Row>
    <Footer>
      <Control ID="SUBTOTAL">
        <Value>1710.32</Value>
      </Control>
    </Footer>
  </Container>
  <AutoKeys />
</Document>

I’d like to end up with something similar to the following output:

VENDOR_NAME     VENDOR_NUMBER   INVOICE_NUMBER  INVOICE_DATE    DESCRIPTION         AMOUNT  INV_SUBTOTAL    SUBTOTAL
CVS             1101            23126           5/13/2014       Pens                50.32   110.32          1710.32
CVS             1101            23126           5/13/2014       Tape                60      110.32          1710.32
CVS             1101            61626           6/1/2014        Microsoft Office    1600    1600            1710.32
Was it helpful?

Solution

select @XML.value('(/Document/Controls/Control[@ID = "VENDOR_NAME"]/Value/text())[1]', 'nvarchar(100)') as VENDOR_NAME,
       @XML.value('(/Document/Controls/Control[@ID = "VENDOR_NUMBER"]/Value/text())[1]', 'int') as VENDOR_NUMBER,
       R1.X.value('(Control[@ID = "INVOICE_NUMBER"]/Value/text())[1]', 'int') as INVOICE_NUMBER,
       R2.X.value('(Control[@ID = "DESCRIPTION"]/Value/text())[1]', 'nvarchar(max)') as DESCRIPTION,
       R2.X.value('(Control[@ID = "AMOUNT"]/Value/text())[1]', 'nvarchar(max)') as AMOUNT,
       C2.X.value('(Footer/Control[@ID = "INV_SUBTOTAL"]/Value/text())[1]', 'nvarchar(max)') as INV_SUBTOTAL,
       C1.X.value('(Footer/Control[@ID = "SUBTOTAL"]/Value/text())[1]', 'nvarchar(max)') as SUBTOTAL
from @XML.nodes('/Document/Container') as C1(X)
  cross apply C1.X.nodes('Row') as R1(X)
  cross apply R1.X.nodes('Container') as C2(X)
  cross apply C2.X.nodes('Row') as R2(X)

SQL Fiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top