【问题标题】:From nested objects to XML document using recursion使用递归从嵌套对象到 XML 文档
【发布时间】:2018-07-22 15:32:06
【问题描述】:

我知道here提供的建议

不过我还是希望得到一些帮助来理解我的代码中的错误。

我有一个从这个类派生的对象列表

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 = "";
    }

}

我主要有这些对象:

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

现在我想通过我的列表和它的孩子来创建一个嵌套的 XML 结构,使用以下规则:

  1. 当 Leaf 对象没有子对象时,过程必须创建一个 &lt;dictionaryitem/&gt; 元素
  2. 当 Leaf 有子级时,该过程必须创建一个 &lt;dictionarygroup&gt;&lt;/dictionarygroup&gt;,其中包含子级,这些子级可以是字典项或字典组,具体取决于它们是否有子级。
  3. dictionaryitem 和 dictionarygroup 具有相同的属性,均派生自 Leaf 对象。

我的递归过程如下:

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;
     }

它产生一个结果,但不是预期的;让我们以这个数据为例:

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);

我希望得到以下结果:

<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" />

相反,我得到了这个:

<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" />

所以每次有孩子时,第一个被用作包含其他兄弟姐妹的分组标签,所以它就像父母一样。

【问题讨论】:

  • 一开始数据初始化有错误(leaf 1代替leaf1_1,leaf2代替leaf1_2)。我现在会发现的另一个问题
  • 当 CreateString 代码执行到 Leaf1_1 时,“if (xmloutput != null)”返回 false 并执行“xmloutput = xml”。之后,当 CreateString 为leaf1_2 运行时,条件“if (xmloutput != null)”返回 true,并且 xmloutput 包含leaf1_1,因此你得到了你不想要的结果
  • 所以 xmloutput.Add(xml) 将新的 XElement 附加为 xmloutput 中存在的 XElement 的子元素;好的,知道如何在前一个 XElement 的对等级别附加新的 XElement 吗?
  • 非常感谢您的回答!
  • 递归 + 循环组合搞砸了 CreateString 方法中的一切

标签: c# xml linq recursion nested


【解决方案1】:

我设法用最少的更改修复了代码。

数据初始化部分:

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);

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;
}

附:当然,这不是指定任务的最佳算法,但我尽量少改动源代码。

【讨论】:

  • 我明白了,非常感谢您的建议,因为它总是对了解问题所在非常有用。
  • 在此期间,我使用 Xml.Serialization 编写了一个新程序:它很容易实现,效果很好,一点也不让我头疼!!
猜你喜欢
  • 2020-10-06
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2020-01-26
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多