How to iterate through every potential XML subelement using SQL Server

I have a large XML file of over 45K contacts and I need to iterate through their subelement transactions into a SQL table. I’ve looked at several solutions to this, using value(), node(), etc…, but no examples appear to have an XML structure close to mine:

<Contacts>
    <Contact>
        <ContactID>1234</ContactID>
        <ContactName>’John Doe’</ContactName>
        <DOB>09031978</DOB>
        <Address>’123 Main Street’</Address>
            <Transactions>
                <Transaction>
                <TransactionID>4490</TransactionID>
                <ProductName>’Recliner’</ProductName>
                <Cost>123.00</Cost>
                <PurchaseDate>07042020
                </Transaction>
                <Transaction>
                <TransactionID>5678</TransactionID>
                <ProductName>’Lamp’</ProductName>
                <Cost>45.00</Cost>
                <PurchaseDate>07042020
                <Transaction>
            </Transactions>
    </Contact>
    <Contact>
        <ContactID>4567</ContactID>
        <ContactName>’Jane Doe’</ContactName>
        <DOB>05191984</DOB>
        <Address>’567 Fake Street’</Address>
            <Transactions>
                <Transaction>
                <TransactionID>4378</TransactionID>
                <ProductName>’Coffee Table’</ProductName>
                <Cost>225.00</Cost>
                <PurchaseDate>07042018
                </Transaction>
            </Transactions>
    </Contact>
</Contacts>

I need these data in a result like below:

ContactID TransactionID ProductName Cost PurchaseDate
1234 4490 Recliner 123.00 4 July 2020
1234 5678 Lamp 45.00 4 July 2020
4567 4378 Coffee Table 225.00 4 July 2018

I’ve tried a query using the following script:

EXEC sp_xml_preparedocument @idoc OUTPUT, @doc  
-- Execute a SELECT stmt using OPENXML rowset provider.  
SELECT *  
FROM OPENXML (@idoc, '/Contacts/Contact/Transactions/Transaction',2)  
WITH (ContactID     int             '../ContactID',  
      TransactionID  int            'TransactionID',  
      ProductName   nvarchar(50)    'ProductName',  
      Cost          float           'Cost',  
      PurchaseDate  date            'PurchaseDate')

But this will return either a null for ContactID; or return only one transaction for each ContactID. But I need it to iterate and get as many transactions as exist for a contact.

Any insights would be most welcome!