IMHO, I recently answered a similar question.
Please try the following conceptual example.
SQL
-- DDL and sample data population, start
-- parent table
DECLARE @state TABLE (stateID INT IDENTITY PRIMARY KEY, stateName VARCHAR(30), abbr CHAR(2), capital VARCHAR(30));
-- child table (1-to-many)
DECLARE @city TABLE (cityID INT IDENTITY PRIMARY KEY, stateID INT, city VARCHAR(30), [population] INT);
-- DDL and sample data population, end
DECLARE @xml XML =
N'<root>
<state>
<StateName>Florida</StateName>
<Abbr>FL</Abbr>
<Capital>Tallahassee</Capital>
<cities>
<city>
<city>Miami</city>
<population>470194</population>
</city>
<city>
<city>Orlando</city>
<population>285713</population>
</city>
</cities>
</state>
<state>
<StateName>Texas</StateName>
<Abbr>TX</Abbr>
<Capital>Austin</Capital>
<cities>
<city>
<city>Houston</city>
<population>2100263</population>
</city>
<city>
<city>Dallas</city>
<population>5560892</population>
</city>
</cities>
</state>
</root>';
DECLARE @cnt INT, @i INT;
-- to preserve unique identifier IDENTITY of a parent table
DECLARE @ParentID INT;
-- count total number of <state> elements
SET @cnt = @xml.value('count(/root/state)', 'INT');
-- loop through XML
SET @i = 1;
WHILE @i <= @cnt BEGIN
INSERT INTO @state (stateName, abbr, capital)
SELECT c.value('(StateName/text())[1]', 'VARCHAR(30)') AS StateName
, c.value('(Abbr/text())[1]', 'CHAR(2)') AS Abbr
, c.value('(Capital/text())[1]', 'VARCHAR(30)') AS Capital
FROM @xml.nodes('/root/state[sql:variable("@i")]') AS t(c)
-- capture last inserted IDENTITY value for the parent table
SET @ParentID = SCOPE_IDENTITY();
INSERT INTO @city (stateID, city, [population])
SELECT @ParentID -- IDENTITY from the parent table
, c.value('(city/text())[1]', 'VARCHAR(30)') AS [population]
, c.value('(population/text())[1]', 'INT') AS BGColor
FROM @xml.nodes('/root/state[sql:variable("@i")]/cities/city') AS t(c)
SET @i += 1;
END
-- test
SELECT * FROM @state;
SELECT * FROM @city;