c#XML到对象的转换不固定复杂性

c#XML到对象的转换不固定复杂性,c#,xml,linq,xml-parsing,xsd,C#,Xml,Linq,Xml Parsing,Xsd,我一直在研究MSDN中的许多XML解析和序列化方法。看看Linq和XSD.exe,似乎没有一个黄金解决方案能像我所寻找的那样脱颖而出 我的问题是什么是最好的方法,如果存在的话 假设我有一个任意复杂的XML。一个可以被这样的类满足的类,假设它们是实质性的 public class nameVal { string name { get; set; } object value { get; set; } } public class

我一直在研究MSDN中的许多XML解析和序列化方法。看看Linq和XSD.exe,似乎没有一个黄金解决方案能像我所寻找的那样脱颖而出

我的问题是什么是最好的方法,如果存在的话

假设我有一个任意复杂的XML。一个可以被这样的类满足的类,假设它们是实质性的

    public class nameVal
    {
        string name { get; set; }
        object value { get; set; }
    }
    public class node
    {
        nameVal self { get; set; }
        List<nameVal> properties { get; set; }
        List<node> children { get; set; }
    };
公共类nameVal
{
字符串名称{get;set;}
对象值{get;set;}
}
公共类节点
{
nameVal self{get;set;}
列表属性{get;set;}
列出子项{get;set;}
};
如何从字符串或文件的源代码并使用c#和MSDN库实现这一点。一些任意方式,如,
foreach(节点中的var-prop)trunk.properties.add(prop)

我已经阅读了这里的十几篇文章和网络上的文章,但是我没有找到一种方法来做到这一点,而不需要事先了解XML,或者从XML创建XSD模式。我只是觉得很奇怪,没有一种任意的解析方法将XML文档放入一个通用的iterable数据结构中


所以。。。方法,库,这不存在的原因,任何信息都会很好

我可以想到两种可能的方法

第一种方法是从XML本身推断XML模式,然后代码从该模式生成C#类。我们已经知道这是可能的,因为XSD.EXE可以从XML文件推断模式

第二种方法是解析XML并填充XML。如果XML在其结构中是完全流动的(即,它有一个任意的模式),那么这将是首选方法。代码如下所示:

public static IEnumerable<dynamic> GetExpandoFromXml(string file, string descendantid)
{
    var expandoFromXml = new List<dynamic>();

    var doc = XDocument.Load(file);
    var nodes = doc.Root.Descendants(descendantid);

    foreach (var element in doc.Root.Descendants(descendantid))
    {
        dynamic expandoObject = new ExpandoObject();
        var dictionary = expandoObject as IDictionary<string, object>;
        foreach (var child in element.Descendants())
        {
            if (child.Name.Namespace == "")
                dictionary[child.Name.ToString()] = child.Value.Trim();
        }
        yield return expandoObject;
    }
}
public静态IEnumerable GetExpandoFromXml(字符串文件,字符串下降)
{
var expandoFromXml=新列表();
var doc=XDocument.Load(文件);
var节点=doc.Root.subjects(degrandAnti);
foreach(doc.Root.substands(degrandAnti)中的var元素)
{
动态expandoObject=新的expandoObject();
var dictionary=expandooobject作为IDictionary;
foreach(元素中的var子元素。子元素()
{
if(child.Name.Namespace==“”)
字典[child.Name.ToString()]=child.Value.Trim();
}
收益率目标;
}
}

如果我正确理解了您的问题,您希望将任何xml映射到您的类。以下是我的尝试:

var nodes = ParseXml(XDocument.Load(filename).Root);


在C#中有几种不同的XML支持方式,但对于一个假设,没有单一的最佳答案

如果您想要真正的序列化,即将XML映射到您定义的类的实例中,则需要修改您的类(例如,属性需要声明为public),并且具有对象类型的成员很棘手(反序列化器如何知道放在那里的类型?)这种方法需要将XML结构的知识嵌入到类中,这听起来不像您想要的

更通用的解决方案是,这些方法使用框架定义的类来表示XML节点和值,而不是您定义的类。常见的选择包括System.XML名称空间中类似DOM的类,或更适合System.XML.Link名称空间中Linq风格处理的新类。有很多关于在这些选项之间进行选择的好文章,比如

但在通用方法中,XML标记和属性不会直接映射到C#property名称和集合,我认为您可能正在寻找。相反,您必须在框架类上使用一些方法来选择所需的数据,例如,XmlDocument有一个SelectSingleNode()方法,可用于使用XPath查询提取特定数据。这导致对XML结构的了解仅限于XPath字符串,而不是嵌入到代码中


希望这能帮助您澄清问题并得到答案。

这绝对是件好事,正是我所希望的。
node ParseXml(XElement root)
{
    var node = new node();

    node.self = new nameVal() { name = root.Name.LocalName, value = (string)root };

    node.properties = root.Attributes()
                          .Select(a => new nameVal() { name = a.Name.LocalName, value = a.Value })
                          .ToList();

    node.children = root.Elements()
                        .Select(e => ParseXml(e))
                        .ToList();

    return node;
}