3

I have a XML file, which I need to import into a SQL Server database. The XML file is build like this:

<report>
  <deltagere>
    <deltager>
    <number>142555267</number>
    <date>29-12-2006</date>
    <name>
      <name>
        <from>01-05-2000</from>
        <to>01-01-2003</to>
        <text>foo</text>
      </name>
      <name>
        <from>01-01-2003</from>
        <to>29-12-2006</to>
        <text>bzz</text>
      </name>
    </name>
    <information>
      <deltagertype>person</deltagertype>
      <leader>John Smith</leader>
      <status>Active</status>
    </information>
    <role>Responsible</role>
    </deltager>
    <deltager>
      <number>4000134982</number>
      <date>05-12-2007</date>
      <name>
        <name>
          <from>07-07-2007</from>
          <to>05-12-2007</to>
          <text>bar</text>
        </name>
      </name>
      <information>
        <deltagertype>person</deltagertype>
        <leader>Wolfgang Smith</leader>
        <status>Active</status>
      </information>
      <role>Responsible</role>
    </deltager>
    ...
  </deltagere>
</report>

As you can see the name attribute can hold multiple names. I have managed to import the XML into my database, but only with the first name attribute. The code I have written so far is:

DECLARE @XmlFile XML

SELECT @XmlFile = BulkColumn
FROM  OPENROWSET(BULK 'C:\input.xml', SINGLE_BLOB) x;

INSERT INTO dbo.deltagere(number, dato, nameFrom, nameTo, nameText, deltagertype, leader, deltagerStatus, deltagerRole)
SELECT
  number = deltagere.value('(number)[1]', 'bigint'),
  dato = deltagere.value('(date)[1]', 'varchar(10)'),
  nameFrom = deltagere.value('(name/name/from)[1]', 'varchar(10)'),
  nameTo = deltagere.value('(name/name/to)[1]', 'varchar(10)'),
  nameText = deltagere.value('(name/name/text)[1]', 'varchar(30)'),
  deltagertype = deltagere.value('(information/deltagertype)[1]', 'varchar(20)'),
  leader = deltagere.value('(information/leader)[1]', 'varchar(50)'),
  deltagerStatus = deltagere.value('(information/status)[1]', 'varchar(50)'),
  deltagerRole = deltagere.value('(role)[1]', 'varchar(50)')
FROM
  @XmlFile.nodes('/report/deltagere/deltager') AS XTbl(deltagere);

Which gives me this output:

| number     | dato       | nameFrom   | nameTo     | nameText | deltagertype | ...
| 142555267  | 29-12-2006 | 01-05-2000 | 01-01-2003 | foo      | person       | ...
| 4000134982 | 05-12-2007 | 07-07-2007 | 05-12-2007 | bar      | person       | ...

I would like to have a row for each name/name. So something like this:

-------------------------------------------------------
| number     | dato       | nameFrom   | nameTo     | nameText | deltagertype | ...
| 142555267  | 29-12-2006 | 01-05-2000 | 01-01-2003 | foo      | person       | ...
| 142555267  | 29-12-2006 | 01-01-2003 | 29-12-2006 | bzz      | person       | ...
| 4000134982 | 05-12-2007 | 07-07-2007 | 05-12-2007 | bar      | person       | ...

and so on.

I'm really lost in how to do this. So I hope any of you have any ideas on how to modify my code to allow this or maybe an different approach on the problem.

1 Answer 1

2

Try this - you need to do a second .nodes() call to enumerate all <name> subnodes:

SELECT
    number = deltagere.value('(number)[1]', 'bigint'),
    dato = deltagere.value('(date)[1]', 'varchar(10)'),
    -- NEW NEW NEW - read from `XC` pseudo columns to get 1-n names
    nameFrom = XC.value('(from)[1]', 'varchar(10)'),
    nameTo = XC.value('(to)[1]', 'varchar(10)'),
    nameText = XC.value('(text)[1]', 'varchar(30)'),
    deltagertype = deltagere.value('(information/deltagertype)[1]', 'varchar(20)'),
    leader = deltagere.value('(information/leader)[1]', 'varchar(50)'),
    deltagerStatus = deltagere.value('(information/status)[1]', 'varchar(50)'),
    deltagerRole = deltagere.value('(role)[1]', 'varchar(50)')
FROM
    @XmlFile.nodes('/report/deltagere/deltager') AS XTbl(deltagere)
CROSS APPLY
    deltagere.nodes('name/name') AS XT2(XC)
Sign up to request clarification or add additional context in comments.

1 Comment

Maybe you can help me out with another question. What if some of the nodes doesn't have any <name> nodes. Then 0 rows is inserted. Any way to just write NULL in the name columns if that is the case?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.