递归/动态地将XML属性添加到单个动态对象中

时间:2015-04-03 04:16:28

标签: c# xml recursion dynamic expandoobject

所以我有一个XML文档,它有多个这样的层:

<root>
<Client id='1' name='bob'>
     <health id='1'>
          <ex id='2'\>
          <ex id='3' \>
     </health>
</Client>
<Client id='1' name='bob'>
     <health id='1'>
          <ex id='2'\>
          <ex id='3' \>
     </health>
</Client>
</root>

我试图以递归方式将XML文档和每个属性传递给ExpandoObject,并递归地将所有子节点添加到ExpandoObject中。所以上面的xml的最终结果将是一个带有客户端属性的ExpandoObject,还有一个包含健康属性的expandoObject和带有&& 39; ex&#39;健康ExpandoObject中的属性。因此,它就像将XML文档放在多维字典(即ExpandoObject)中。

我在递归方面遇到了很多麻烦,令我困惑的是硬核,我似乎无法让它发挥作用。有没有人知道我如何递归遍历XDocument并为每个子级添加一个ExpandoObject,但如果它的深度级别相同,则将多个ExpandoObjects添加到它上面的对象中?

我知道这可能会让你感到困惑,因为我也很困惑,但最终对象应该是这样的:

对象asd = [客户端属性] +(ExpandoObject asd2 = [健康属性] +(ExpandoObject asd3 = ex + ExpandoObject asd4属性= ex2的属性)

2 个答案:

答案 0 :(得分:0)

到目前为止,我找到了一些对我有用的代码。

 public static class XmlDocumentExtension
{
    public static dynamic ToObject(this XmlDocument document)
    {
        XmlElement root = document.DocumentElement;
        return ToObject(root, new ExpandoObject());
    }

    private static dynamic ToObject(XmlNode node, ExpandoObject config, int count = 1)
    {
        var parent = config as IDictionary<string, object>;
        foreach (XmlAttribute nodeAttribute in node.Attributes)
        {
            var nodeAttrName = nodeAttribute.Name.ToString();
            parent[nodeAttrName] = nodeAttribute.Value;
        }
        foreach (XmlNode nodeChild in node.ChildNodes)
        {
            if (IsTextOrCDataSection(nodeChild))
            {
                parent["Value"] = nodeChild.Value;
            }
            else
            {
                string nodeChildName = nodeChild.Name.ToString();
                if (parent.ContainsKey(nodeChildName))
                {
                    parent[nodeChildName + "_" + count] = ToObject(nodeChild, new ExpandoObject(), count++);
                }
                else
                {
                    parent[nodeChildName] = ToObject(nodeChild, new ExpandoObject());
                }
            }
        }
        return config;
    }

    private static bool IsTextOrCDataSection(XmlNode node)
    {
        return node.Name == "#text" || node.Name == "#cdata-section";
    }
}

答案 1 :(得分:0)

我认为循环执行将为您提供帮助(将“ this”更改为要从xml属性设置其属性的类的对象):

public void AddXElementAttributesToThisClass(XElement xe)
        {
            ExpandoObject obj = new ExpandoObject();
            foreach (var attribute in xe.Attributes())
            {
                 (obj as IDictionary<string, object>)[attribute.Name.ToString()] = attribute.Value.Trim();
            }
            var dynamicDictionary = obj as IDictionary<string, object>;
            foreach (var property in this.GetType().GetProperties())
            {
                var propName = property.Name;
                var value = property.GetValue(this, null);
                if (dynamicDictionary.ContainsKey(propName) && value != dynamicDictionary[propName])
                {
                    var foundXmlObj= dynamicDictionary[propName];
                    property.SetValue(this, foundXmlObj);
                }
            }
        }