Search code examples
c#.netxmlxelement

Nested XML node not lining up correctly


I am attempting to produce the below XML

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Application>
    <organisation>
        <organisation_id>0</organisation_id>
    </organisation>
    <address>
        <address1>12345</address1>
        <address2>qqqqq</address2>
        <address3>ddddd</address3>
    </address>
    <Customer>
        <custID>652</custID>
        <address1>12345</address1>
        <references>
            <f_ref>456789</f_ref>

            <licenses>
                <id>3654</id>
                <image>\photo\123.jpg</image>
            </licenses>

        </references>

        <type>
            <sort>1</sort>
            <date>12/12/1997</date>
        </type>
        <internal>
            <auto>true</auto>
            <deliver>true</deliver>
        </internal>
    </Customer>
</Application>

For that reason i have the below code:

MyDocument MyDoc = new MyDocument(
        new XDeclaration("1.0", "utf-8", "no"));
        XElement MyRoot = new XElement("Application",
                new XElement("organisation",
                    new XElement("organisation_id", "0")),
                    new XElement("address",
                        new XElement("address1", "123456"),
                        new XElement("address2", "qqqqq"),
                        new XElement("address3", "ddddd")));
        MyDoc.Add(MyRoot);

        foreach (var c in GetCustomers())
        {
            XElement Customers = new XElement("Customer",
                            new XElement("custID", "652"),
                                        new XElement("address1", "12345")),
                                            new XElement("references",
                                            new XElement("f_ref", "456789")));
            MyRoot.Add(Customers);

            foreach (License l in c.Licenses)
            {
                XElement Licenses = new XElement("licenses",
                      new XElement("id", "3654"),
                      new XElement("image", "\photo\123.jpg"));
                MyRoot.Add(Licenses);
            }


            XElement Type = new XElement("type",
                          new XElement("sort", "1"),
                          new XElement("date", "12/12/1997"));
            MyRoot.Add(Type);

            XElement Internal = new XElement("internal",
                new XElement("auto", "true"),
                new XElement("deliver", "true"));
            MyRoot.Add(Internal);
        }

which produces the below XML

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Application>
  <organisation>
    <organisation_id>0</organisation_id>
  </organisation>
  <address>
    <address1>12345</address1>
    <address2>qqqqq</address2>
    <address3>ddddd</address3>
  </address>
  <Customer>
    <custID>652</custID>
    <address1>12345</address1>
    <references>
      <f_ref>456789</f_ref>
    </references>
  </Customer>
  <licenses>
    <id>3654</id>
    <image>\photo\123.jpg</image>
  </licenses>
  <type>
    <sort>1</sort>
    <date>12/12/1997</date>
  </type>
  <internal>
    <auto>true</auto>
    <deliver>true</deliver>
  </internal>
</Application>

I have moved the MyRoot.Add method around, even attempted to add the foreach loop inside the XElement (which gives me a syntax error) but im not sure how to produce the XML im after?


Solution

  • MyRoot is your root Application element. That's where you're adding licences, type, and internal, so that's where they'll get written.

    You should be adding them to customers instead, so use Customers.Add for type and internal. licences should be included inside the references constructor - though it may be easier to pull the creation of references out in a similar way to type and internal.

    So, after a bit of re-arranging to make the code compile:

    var doc = new XDocument(
        new XDeclaration("1.0", "utf-8", "no"));
    
    var root = new XElement("Application",
        new XElement("organisation",
            new XElement("organisation_id", "0")),
        new XElement("address",
            new XElement("address1", "123456"),
            new XElement("address2", "qqqqq"),
            new XElement("address3", "ddddd")));
    
    doc.Add(root);
    
    var customers = new XElement("Customer",
        new XElement("custID", "652"),
        new XElement("address1", "12345")
        );
    
    root.Add(customers);
    
    var references = new XElement("references",
        new XElement("f_ref", "456789"));
    
    var licenses = new XElement("licenses",
        new XElement("id", "3654"),
        new XElement("image", @"\photo\123.jpg"));
    
    references.Add(licenses);
    
    var type = new XElement("type",
        new XElement("sort", "1"),
        new XElement("date", "12/12/1997"));
    
    customers.Add(type);
    
    var @internal = new XElement("internal",
        new XElement("auto", "true"),
        new XElement("deliver", "true"));
    
    customers.Add(@internal);
    

    See this fiddle for a working demo.