一聚教程网:一个值得你收藏的教程网站

热门教程

Linq学习教程 Linq to Xml读取复杂xml及Linq to js使用

时间:2022-06-25 03:36:31 编辑:袖梨 来源:一聚教程网

Linq to Xml读取复杂xml(带命名空间)

xml的操作方式有多种,但要论使用频繁程度,博主用得最多的还是Linq to xml的方式,觉得它使用起来很方便,就用那么几个方法就能完成简单xml的读写。之前做的一个项目有一个很变态的需求:C#项目调用不知道是什么语言写的一个WebService,然后添加服务引用总是失败,通过代理的方式动态调用也总是报错,最后没办法,通过发送原始的WebRequest请求直接得到对方返回的一个xml文件。注意过webservice的wsdl文件的朋友应该知道这个是系统生成的xml文件,有点复杂,研究了半天终于能正常读写了。今天在这里和大家分享下。

1、介绍之前,首先回顾下Linq to xml的方式读写简单xml的方法

(1)读取xml




  
  
var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"datatest.xml");
XDocument adList = XDocument.Load(strPath);
var ad = from a in adList.Descendants("BizADsList").Elements("adData")
         select new
         {
             image = a.Attribute("image").Value,
             link = a.Attribute("link").Value,
             title = a.Attribute("title").Value
         };
string s = "";
foreach (var a in ad)
    s += a.image;





(2)写xml

/// 
/// 根据得到的Document集合生成XML
/// 
/// 
/// 
/// 
/// 
private static void SaveXmlByLstDocument(List lstDocumentBD, Document docNE, string strSpiderTime, string strNewRate)
{
    try
    {
        XDocument xDoc = new XDocument();
        XElement xRoot = new XElement(CSpiderConst.XML_ELE_ROOT);
        //1.构造Device节点
        XElement xDevice = new XElement(CSpiderConst.XML_ELE_DEVICE);
        //2.构造NE节点
        XElement xNE = new XElement(CSpiderConst.XML_ELE_NE);
        foreach (var oDocNE in docNE)
        {
            XElement xItem = new XElement(CSpiderConst.XML_ELE_ITEM, new XAttribute(CSpiderConst.XML_PROP_NAME, oDocNE.Key), oDocNE.Value);
            xNE.Add(xItem);
        }
        //这里增加一个节点用来保存当前这次的利用率和当次的采集时间
        AddNewRateAndSpiderTime(strSpiderTime, strNewRate, xNE);
        xDevice.Add(xNE);
        //3.循环构造BD节点并添加到Device节点中
        foreach (var oDocument in lstDocumentBD)
        {
            XElement xBD = new XElement(CSpiderConst.XML_ELE_BD);
            foreach (var oDocBD in oDocument)
            {
                XElement xItem = new XElement(CSpiderConst.XML_ELE_ITEM, new XAttribute(CSpiderConst.XML_PROP_NAME, oDocBD.Key), oDocBD.Value);
                xBD.Add(xItem);
            }
            AddNewRateAndSpiderTime(strSpiderTime, strNewRate, xBD);
            xDevice.Add(xBD);
        }
        xRoot.Add(xDevice);
        xDoc.Add(xRoot);
        //4.保存到采集器本地,以服务器的时间和网元的AssetID来命名
        var strDirectoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ReportFailed\");
        if (!Directory.Exists(strDirectoryPath))
        {
            Directory.CreateDirectory(strDirectoryPath);
        }
        xDoc.Save(strDirectoryPath + docNE[TBLDeviceLCBB.PROP_ASSETID] + "_" + strSpiderTime.Replace(":", "_") + ".xml");
    }
    catch
    {
        CLogService.Instance.Debug("保存XML失败");
    }
}



通过XDocument、XElement对象和Element()、Elements()两个方法能完成大部分xml文件的操作。

2、进入今天的正题:读写带命名空间的xml文件。

首先来看一段xml



  
    
      test
    
    
      
        
          
          
        
      
    
  



第一次看到这个文件确实让人萌神了,比如需要取一个msdata:IsDataSet="true"这个属性,该怎么取...

解析之前,先来分析下这段xml,这段里面有一个xmlns属性,这个属性是每一个标签自带的属性,不信你可以新建一个xml文件,然后在任何一个标签里面输入xmlns属性,后面都会出来很多的系统自带的命名空间。这个属性表示所属标签在哪个命名空间下面,所以在取的时候要带上这个命名空间。

先来看看解析的代码:

var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"datatest.xml");
var oRoot = XDocument.Load(strPath);
//取DataSet标签
var oDataSet = oRoot.Element(XName.Get("DataSet", "http://WebXml.com.cn/"));
//取schema标签
var oSchema = oDataSet.Element(XName.Get("schema", "http://www.w3.org/2001/XMLSchema"));
//取element标签
var oElement = oSchema.Element(XName.Get("element", "http://www.w3.org/2001/XMLSchema"));//这两个节点都是以xs打头,所以命名空间都是xs的命名空间
//取element标签下面的IsDataSet属性
var oElementValue = oElement.Attribute(XName.Get("IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));
//取aa标签
var oAA = oSchema.Element(XName.Get("aa", "urn:schemas-microsoft-com:xml-msdata"));




我们来解析下几个关键的地方:

(1)我们来解析下



这一句,最前面的"xs"表示标签所属命名空间的变量,xmlns:xs="http://www.w3.org/2001/XMLSchema"这个表示xs这个命名空间的值。所以要得到schema这个标签需要带上命名空间var oSchema = oDataSet.Element(XName.Get("schema", "http://www.w3.org/2001/XMLSchema"));这个标签还定义了另一个命名空间xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"。

(2)再来看看aa标签

 
      test
 



msdata就是上面schema标签里面定义的另一个命名空间,表示aa标签属于msdata命名空间下面。

(3)再看来看属性的取法:



如果要取msdata:IsDataSet="true",由于这个属性也带有命名空间,所以取属性时也要加上命名空间了。所以需要这样取。

var oElementValue = oElement.Attribute(XName.Get("IsDataSet", "urn:schemas-microsoft-com:xml-msdata"));


现在大伙们应该对这种xml有一个更加清晰的认识了吧。其实一般情况下这种场景比较少见,因为这么复杂的xml一般是由引用服务时代理对象去解析的。但如果真的有这么变态的需求我们也不用担心了。在此记录下,以后如果大家遇到希望能节约大伙的时间。


Linq to js使用小结

1、什么是Linq to js :C# 3.0推出了.Net独有的新特性:Linq。自从有了Linq,程序员再也不用担心对集合的操作了。同理,Linq to js 当然也就是对前端集合变量进行操作的一种技术框架。

2、怎么使用:因为是前端框架,所以你懂得,只需要引用一个js文件即可。这里还是附上官网地址:http://jslinq.codeplex.com/.这上面有文件和Demo,可以上去看看。使用方式主要有两种:使用方法一、直接引用js文件;使用方法二、使用Nuget Package 安装Linq to js。在PM安装控制台中输入Install-Package jslinq。

本篇以Linq to js的lamada表达式写法的方式来以此介绍常用方法。我们从官网上面下载下载的文件如下图

我们只需要引用linq.js文件即可。

(1)条件查询:Where

var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 21 },
            { Name: "Lilei", Age: 18 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    var arrRes = Enumerable.From(myList).Where("x=>x.Name=='Jim'").ToArray();





arrRes的结果为 [{"Name":"Jim","Age":20}]

我们来看看这种写Lamada表达式的原型:

var arrRes = Enumerable.From(myList).Where(function (i) { return i.Name=='Jim'; });

参数i是对应的集合里面的实体模型,返回类型为bool类型。有没有和C#里面的扩展函数Where的定义很像:public static IEnumerable Where(this IEnumerable source, Func predicate);参数Func predicate为匿名委托,需要传入实体模型TSource,然后返回值为bool类型。其实感觉linq to js的使用就是参照c#里面的定义来的。

 

(2)条件选择:Select

var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 21 },
            { Name: "Lilei", Age: 18 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    var arrRes = Enumerable.From(myList).Select("x=>x.Age*10").ToArray();




arrRes得到结果 [200,210,180,140,250]

 

(3)排序、去重:OrderBy、Distinct


var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 21 },
            { Name: "Lilei", Age: 18 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    var arrRes = Enumerable.From(myList).OrderBy("x=>x.Age").ToArray();//降序OrderByDescending()



得到的结果会按照Age排序。

var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 20 },
            { Name: "Lilei", Age: 20 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    var arrRes = Enumerable.From(myList).Distinct("x=>x.Age").ToArray();





得到的结果集合的数量为3个:[ { Name: "Jim", Age: 20 }, { Name: "John", Age: 14 }, { Name: "LinTao", Age: 25 }]。

 

(4)遍历:ForEach

var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 20 },
            { Name: "Lilei", Age: 20 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    Enumerable.From(myList).ForEach(function(value, index){
         document.write("值="+value+",索引="+index);   
 });




很显然两个参数:一个是值,另一个是当前索引
 

(5)取唯一对象:First、FirstOrDefault、Last、LastOrDefault、Single、SingleOrDefault

var myList = [
            { Name: "Jim", Age: 20 },
            { Name: "Kate", Age: 20 },
            { Name: "Lilei", Age: 20 },
            { Name: "John", Age: 14 },
            { Name: "LinTao", Age: 25 }
    ];
    var arrRes = Enumerable.From(myList).FirstOrDefault("x=>x.Age>18");





其他几个用法和这个类似。这个没什么好说的。


(6)Skip、Take

Enumerable.Range(1,10).Skip(5)//结果[6,7,8,9,10]
Enumerable.Range(1,10).Take(5)//结果[1,2,3,4,5]



(7)取交集、取差集、合并

var array1 = [1,412,5,3,5,412,7];
var array2 = [20,12,5,5,7,310];
Enumerable.From(array1).Except(array2)
//结果3,412,1
var array1 = [1,412,5,3,5,412,7];
var array2 = [20,12,5,5,7,310];
Enumerable.From(array1).Intersect(array2)
//结果5,7
var array1 = [1,412,5,3,5,412,7];
var array2 = [20,12,5,5,7,310];
Enumerable.From(array1).Union(array2)
//结果是两个结果集里面所有值,并自动去重



 

当然还有其他一些不常用的方法。有兴趣可以查看文档。其实linq to js还有一种支持jquery的写法。如下:

Enumerable.Range(1,10).Where("$%2==0")
//等价于
Enumerable.Range(1,10).Where("x=>x%2==0")



但引用文件的时候需要引用jquery.linq.js这个文件。就是写法不同,效果完全一样,选哪一种就是习惯问题了。博主更加倾向lamada方式的写法,因为和C#用法可以保持一致。

热门栏目