Question

i am a newbie in XmlDocument.i want to create nested xml document in c#.through some reaserach i fount that XmlDocument are recommended way to create xml if size is small.

i am having some trouble while creating nested tags

code:

XmlDocument doc = new XmlDocument();
XmlDeclaration xDeclare = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xDeclare, root);
XmlElement el = (XmlElement)doc.AppendChild(doc.CreateElement("FIXML"));
el.AppendChild(doc.CreateElement("Header")).InnerText = "";
el.AppendChild(doc.CreateElement("RequestHeader")).InnerText = "";
el.AppendChild(doc.CreateElement("MessageKey")).InnerText = "";
el.AppendChild(doc.CreateElement("RequestUUID")).InnerText = "938692349";
Console.WriteLine(doc.OuterXml);

its giving output as

<?xml version="1.0" encoding="UTF-8"?>
<FIXML>
    <Header></Header>
    <RequestHeader></RequestHeader>
    <MessageKey></MessageKey>
    <RequestUUID>938692349</RequestUUID>
</FIXML>

but it should be like

<?xml version="1.0" encoding="UTF-8"?>
<FIXML>
    <Header>
        <RequestHeader>
            <MessageKey>
                <RequestUUID>938692349</RequestUUID>
            </MessageKey>
        </RequestHeader>
    </Header>
</FIXML>
Was it helpful?

Solution

Much easier with the newer XML API (XDocument)

var doc = 
    new XElement("FIXML",        // you can optionally add an XDocument as outer element
      new XElement ("Header", 
          .... // more child elements, values and/or attributes
          new XElement("RequestUUID", 938692349)
      ));


doc.Save(fileName);

OTHER TIPS

You are appending all your children to the root element. You probably need something along the lines of:

XmlDocument doc = new XmlDocument();
XmlDeclaration xDeclare = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement documentRoot = doc.DocumentElement;
doc.InsertBefore(xDeclare, documentRoot);
XmlElement rootEl = (XmlElement)doc.AppendChild(doc.CreateElement("FIXML"));
XmlElement child1 = (XmlElement)rootEl.AppendChild(doc.CreateElement("Header"));
XmlElement child2 = (XmlElement)child1.AppendChild(doc.CreateElement("RequestHeader"));
...

The problem is in your following statement....

el.AppendChild(doc.CreateElement("Header")).InnerText = "";
el.AppendChild(doc.CreateElement("RequestHeader")).InnerText = "";
el.AppendChild(doc.CreateElement("MessageKey")).InnerText = "";
el.AppendChild(doc.CreateElement("RequestUUID")).InnerText = "938692349";

you are appending everything to el. This is why you are getting the wrong out put instead as per your output you should do like below...

XmlElement header = doc.CreateElement("Header")).InnerText = "";
XmlElement RequestHeader = doc.CreateElement("RequestHeader")).InnerText = "";
header.AppendChild(RequestHeader);

This code will help to achieve expected output.

If you want to do this dynamically using XElement. Assuming your input is present in some kind of collection or Array. You can try the below method.

List<string> xmlList = new List<string>();
        xmlList.Add("FIXML");
        xmlList.Add("Header");
        xmlList.Add("RequestHeader");
        xmlList.Add("RequestUUID");

        XElement parentNode = null;
        string lastParent = null;

        foreach (var item in xmlList)
        {
            if (parentNode == null)
            {
                parentNode = new XElement(item);
                lastParent = XmlConvert.EncodeName(item);
            }
            else
            {
                var ln = parentNode.DescendantsAndSelf().FirstOrDefault(x => x.Name.LocalName == lastParent);
                ln.Add(new XElement(XmlConvert.EncodeName(item)));
                lastParent = XmlConvert.EncodeName(item);


            }
        }

        Console.WriteLine(parentNode);
        Console.ReadLine();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top