欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  技术分享

使用ExpandoObject将XML转换为动态对象_XML怎么转对象

程序员文章站 2022-03-01 16:29:50
...

简介

我一直在网上找XML的读取方法,并把它转换为一个对象

我的目的是动态加载XML文、并转换成对象

由于每个XML定义模式都截然不同、我想用dynamic关键字来加载XML文档,并访问它作为一个简单的对象

查阅了一些资料后,我发现了一些例子,所使用的都是ExpandoObject

不幸的是,他们要么写一个对象转换为XML或如何使用XML到LINQ的映射一个特定的动态类/对象

所以,我最后写加载XML文档,并把它转换成一个简单的对象小递归方法

话不多说、直接上代码

private static dynamic _getExpandoFromXml(String file, XElement node = null)
{
    if (String.IsNullOrWhiteSpace(file) && node == null) return null;
    // If a file is not empty then load the xml and overwrite node with the
    // root element of the loaded document
    if (!String.IsNullOrWhiteSpace(file))
    {
        var doc = XDocument.Load(file);
        node = doc.Root;
    }
    dynamic result = new ExpandoObject();
    var pluralizationService = System.Data.Entity.Design.PluralizationServices.
    PluralizationService.CreateService(CultureInfo.CurrentCulture);
    foreach (var gn in node.Elements())
    {
        // The code determines if it is a container node based on the child
        // elements with the same name. If there is only one child element,
        // then it uses the PluralizationService to determine if the 
		//pluralization of the child elements name 
        // matches the parent node. If so then it´s most likely a collection 
        var isCollection = gn.HasElements &&
            ( 
                gn.Elements().Count() > 1 && gn.Elements().All
                (e => e.Name.LocalName.ToLower() == gn.Elements()
				.First().Name.LocalName) ||
                gn.Name.LocalName.ToLower() == pluralizationService.Pluralize
                (gn.Elements().First().Name.LocalName).ToLower()
            );
                    
        var p = result as IDictionary<String, dynamic>;
        var values = new List<dynamic>();
        // If the current node is a container node then we want to skip adding
        // the container node itself, but instead we load the children elements
        // of the current node. If the current node has child elements then load
        // those child elements recursively
        if (isCollection)
            foreach (var item in gn.Elements())
            {
                values.Add((item.HasElements) ? _getExpandoFromXml(null, item) :
                    item.Value.Trim());
            }
        else
            values.Add((gn.HasElements) ? _getExpandoFromXml(null, gn) :
                gn.Value.Trim());

        // Add the object name + value or value collection to the dictionary
        p[gn.Name.LocalName] = isCollection ? values : values.FirstOrDefault();
    }
    return result;
}


示例XML

<?xml version="1.0"?>
 <License>
    <RegisteredUser>Remco Reitsma</RegisteredUser>
    <Company>Xtraworks.com</Company>
    <Sites>
        <Site>
            <Host>xtraworks.com</Host>
            <ExpireDate>15/12/2099</ExpireDate>
        </Site>
        <Site>
            <Host>test.com</Host>
            <ExpireDate>15/12/2099</ExpireDate>
        </Site>
    </Sites>
    <Modules>
        <Module>
            <Name>SEO Package</Name>
            <Controller>SEO</Controller>
            <Version>0.0.1</Version>
            <Tables>
                <Table>
                    <Name>SEO_Site</Name>
                </Table>
                <Table>
                    <Name>SEO_Pages</Name>
                </Table>
            </Tables>
        </Module>
    </Modules>
</License>


使用示例

dynamic license = _getExpandoFromXml(´path to xml file´);
    
// Getting the values from the dynamic object is really easy now.
var registeredUser = license.RegisteredUser;
var companyName = license.Company;

// Getting a collection is just as easy as it simply returns a list
var sites = license.Sites;
foreach(var site in sites)
{ 
   var host = site.Host;
}


好了、到这里就可读取一个简单的XML了、希望对大家有帮助