2

I'm aware about the advise provided here

but nevertheless I would like some help to understand what in my code is wrong.

I have a List of objects derived from this class

public class Leaf
{
    public String key { get; set; }
    public String id { get; set; }
    public String value { get; set; }

    public List<Leaf> branch { get; set; } //children

    public Leaf()
    {
        branch = new List<Leaf>();
        key = "";
        id = "";
        value = "";
        parent_id_value = "";
    }

}

In main I have these objects:

List<Leaf> tree = new List<Leaf>();
 XElement xmloutput = new XElement("root");

Now I would like to go through my list and its children in order to create a nested XML structure, using the following rules:

  1. When the Leaf object ha no children the procedure has to create a <dictionaryitem/> element
  2. When the Leaf has children the procedure has to create a <dictionarygroup></dictionarygroup>, that contains the children, which are either dictionaryitem or dictionarygroup depending on they have themselves children or not.
  3. Both dictionaryitem and dictionarygroup have the same attributes, derived from the Leaf object.

My recursive procedure is the following:

public static XElement CreateString(List<Leaf> tree, XElement xmloutput)
     {
         XElement xml = null;
         foreach(Leaf lf in tree)
         {
             if(lf.branch.Count > 0 && lf.branch[0].id!="")
             {

                 xml = new XElement("dictionarygroup",
                     new XAttribute("codeScheme", 1),
                     new XAttribute("codeValue", lf.id),
                     new XAttribute("codeMeaning", lf.value),
                     new XAttribute("codeSchemeVersion", "01"),
                     new XAttribute("isCancelled", "false"),
                     new XElement(CreateString(lf.branch, null))
                     );

             }
             else
             {
                 xml = new XElement("dictionaryItem",
                   new XAttribute("codeScheme", 1),
                   new XAttribute("codeValue", lf.id),
                   new XAttribute("codeMeaning", lf.value),
                   new XAttribute("codeSchemeVersion", "01"),
                   new XAttribute("isCancelled", "false")
                   );
             }

             if (xmloutput != null)
                 xmloutput.Add(xml);
             else
                 xmloutput = xml;

             xml = null;
         }

         return xmloutput;
     }

It produces a result, but not the expected one; let's consider this data as an example:

List<Leaf> tree = new List<Leaf>();

        Leaf leaf1 = new Leaf();
        leaf1.key = "L1";
        leaf1.id = "257170";
        leaf1.value = "house";

        Leaf leaf2 = new Leaf();
        leaf2.key = "L1";
        leaf2.id = "44444";
        leaf2.value = "mouse";

        Leaf leaf1_1 = new Leaf();
        leaf1_1.key = "L2";
        leaf1_1.id = "323233";
        leaf1_1.value = "window";

        Leaf leaf1_2 = new Leaf();
        leaf1_2.key = "L2";
        leaf1_2.id = "666666";
        leaf1_2.value = "door";

        leaf1.branch.Add(leaf1_1);
        leaf1.branch.Add(leaf1_2);

        tree.Add(leaf1);
        tree.Add(leaf2);

I expect the following result:

<root>
<dictionarygroup codeScheme="1" codeValue="257170" codeMeaning="house" codeSchemeVersion="01" isCancelled="false">
    <dictionaryItem codeScheme="1" codeValue="323233" codeMeaning="window" codeSchemeVersion="01" isCancelled="false" />
    <dictionaryItem codeScheme="1" codeValue="666666" codeMeaning="door" codeSchemeVersion="01" isCancelled="false" />
</dictionarygroup>
<dictionaryItem codeScheme="1" codeValue="44444" codeMeaning="mouse" codeSchemeVersion="01" isCancelled="false" />

Instead I get this:

<root>
<dictionarygroup codeScheme="1" codeValue="257170" codeMeaning="house" codeSchemeVersion="01" isCancelled="false">
    <dictionaryItem codeScheme="1" codeValue="323233" codeMeaning="window" codeSchemeVersion="01" isCancelled="false">
        <dictionaryItem codeScheme="1" codeValue="666666" codeMeaning="door" codeSchemeVersion="01" isCancelled="false" />
    </dictionaryItem>
</dictionarygroup>
<dictionaryItem codeScheme="1" codeValue="44444" codeMeaning="mouse" codeSchemeVersion="01" isCancelled="false" />

So everytime there are children the first is used as a grouping tag that contains the other siblings, so it acts like a parent.

5
  • at first, you have an error in data initialization (leaf 1 instead of leaf1_1, leaf2 instead of leaf1_2). the other problem I will find out now Commented Feb 12, 2018 at 13:21
  • When the CreateString code execution gets to leaf1_1 "if (xmloutput != null)" returns false and "xmloutput = xml" executes. And after it, when CreateString runs for leaf1_2, the condition "if (xmloutput != null)" returns true, and xmloutput contains leaf1_1, and because of it you get the result you don't want Commented Feb 12, 2018 at 13:31
  • So xmloutput.Add(xml) attaches the new XElement as child of the XElement that exists in xmloutput; ok, any idea how to attach the new XElement at the peer level of the previous XElement? Commented Feb 12, 2018 at 13:41
  • Many thanks for the answers! Commented Feb 12, 2018 at 13:42
  • Recursion + loop combination messes up everything in CreateString method Commented Feb 12, 2018 at 13:43

1 Answer 1

4

I managed to fix the code with minimal changes.

Data init part:

List<Leaf> tree = new List<Leaf>();

Leaf leaf1 = new Leaf();
leaf1.key = "L1";
leaf1.id = "257170";
leaf1.value = "house";

Leaf leaf2 = new Leaf();
leaf2.key = "L1";
leaf2.id = "44444";
leaf2.value = "mouse";

Leaf leaf1_1 = new Leaf();
leaf1_1.key = "L2";
leaf1_1.id = "323233";
leaf1_1.value = "window";

Leaf leaf1_2 = new Leaf();
leaf1_2.key = "L2";
leaf1_2.id = "666666";
leaf1_2.value = "door";

leaf1.branch.Add(leaf1_1);
leaf1.branch.Add(leaf1_2);

tree.Add(leaf1);
tree.Add(leaf2);

//Create root element
XElement parentElement = new XElement("Root");

var result = CreateCorrectString(tree, parentElement);

Implementation of CreateString:

public static XElement CreateCorrectString(List<Leaf> tree, XElement parent)
{
    XElement xml = null;
    foreach (Leaf lf in tree)
    {
        if (lf.branch.Count > 0 && lf.branch[0].id != "")
        {
            xml = new XElement("dictionarygroup",
                new XAttribute("codeScheme", 1),
                new XAttribute("codeValue", lf.id),
                new XAttribute("codeMeaning", lf.value),
                new XAttribute("codeSchemeVersion", "01"),
                new XAttribute("isCancelled", "false")
                );

            CreateCorrectString(lf.branch, xml);
        }
        else
        {
            xml = new XElement("dictionaryItem",
                new XAttribute("codeScheme", 1),
                new XAttribute("codeValue", lf.id),
                new XAttribute("codeMeaning", lf.value),
                new XAttribute("codeSchemeVersion", "01"),
                new XAttribute("isCancelled", "false")
                );

        }

        parent.Add(xml);

    }

    return parent;
}

P.S. Of course, this is not the best algorithm for the specified task, but I tried to change the source code as less as possible.

Sign up to request clarification or add additional context in comments.

2 Comments

I've got the point, thanks a lot for the advice since it is always very useful to udertand what is going wrong.
In the meantime I've written a new procedure using the Xml.Serialization: it is quite easy to implement, it works very well and it gave me no headache at all!!

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.