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

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

(1)读取xml

<?xml version="1.0" encoding="utf-8"?>

<BizADsList>

  <adData aid="1" image="baidu.jpg" link="www.baidu.com" title="百度"/>

  <adData aid="2" image="qq.jpg" link="www.qq.com" title="腾讯"/>

</BizADsList>
var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\test.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

        /// <summary>
/// 根据得到的Document集合生成XML
/// </summary>
/// <param name="lstDocumentBD"></param>
/// <param name="docNE"></param>
/// <param name="strSpiderTime"></param>
/// <param name="strNewRate"></param>
private static void SaveXmlByLstDocument(List<Document> 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);
}
//这里增加一个<Item name='NewRate'>和<Item name='SpiderTimeEx'>节点用来保存当前这次的利用率和当次的采集时间
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

<?xml version="1.0" encoding="utf-8" ?>
<DataSet xmlns="http://WebXml.com.cn/">
<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="getRegion">
<msdata:aa>
test
</msdata:aa>
<xs:element name="getRegion" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
<xs:element name="Province">
<xs:sequence>
<xs:element name="RegionID" type="xs:string" minOccurs="0"/>
<xs:element name="RegionName" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:element>
</xs:element>
</xs:schema>
</DataSet>

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

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

先来看看解析的代码:

var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"data\test.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:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="getRegion">

这一句,最前面的"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标签

 <msdata:aa>
test
</msdata:aa>

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

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

<xs:element name="getRegion" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">

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

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

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

Linq to Xml读取复杂xml(带命名空间)的更多相关文章

  1. XML记一次带命名空间的xml读取

    public static void ReadXML(string xmlUrl) { //判断文件是否存在 if (!File.Exists(xmlUrl)) { Console.WriteLine ...

  2. C#读取带命名空间的xml

    首先带有命名空间的xml读取可以使用Xml.Linq,也可以使用xpath,本文将采用xpath的方式解析. 原文参考了:https://www.cnblogs.com/duanjt/p/544054 ...

  3. Linq创建带命名空间、前缀、Soap格式的XML

    关于XML,我也是刚接触,关于一般常见的XML,博客园.CSDN上的资料很多,对于不常见的带命名空间.前缀.Soap格式的XML的描述相对来说寥寥无几,上一篇我写到了对相对复杂的XML的读操作,下面说 ...

  4. Linq解析带命名空间、前缀、Soap格式的XML

    关于XML,经常会用到,XML有一般的,同样也有二般的,更不要觉得会操作基础的XML就觉得自己已经精通XML操作,文中是对解析XML的方法进行介绍 1. 一般XML <?xml version= ...

  5. C#读取带命名空间的xml,xaml文件的解决方案

    使用C#读取xml文件有三种常用的方式: 1.xmlDocument 2.XmlTextReader 3.Linq To Xml 但是这些方式在读写有些带命名空间的xml时就不知道怎么办了(例如把xa ...

  6. C#使用Linq To XML读取XML,Linq生成XML,Linq创建带属性或带节点XML

    using System; using System.Linq; using System.Xml.Linq; namespace Sample2 { class Program { static v ...

  7. Linq to XML 读取XML 备忘笔记

    本文转载:http://www.cnblogs.com/infozero/archive/2010/07/13/1776383.html Linq to XML 读取XML 备忘笔记 最近一个项目中有 ...

  8. 带命名空间的XML的dom4j应用<转>

    Element root = document.getRootElement();     List   recordenvlist = document.selectNodes("//gm ...

  9. dom4j解析带命名空间的xml文件

    文件内容如下 <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=& ...

随机推荐

  1. 【单页应用】全局控制器app应该干些什么?

    前言 之前,我们形成了页面片相关的mvc结构,但是该结构还仅适用于view(页面)级,那么真正的全局控制器app应该干些什么事情呢?我觉得至少需要干这些: 功能点 ① 提供URL解析机制,以便让控制器 ...

  2. 字体属性设置(一):谷歌浏览器12px以下字体的显示;方法和原理

    前言: chrome 谷歌浏览器默认的字体大小为16px:可以通过设置font-size来设置字体大小但是当设置到12px以下的时候字体大小不再改变:对于想设置其他大小的字体就很头疼,本文参考网上的方 ...

  3. 阻止默认事件event.preventDefault();

    阻止浏览器默认事件.什么是默认事件,例如浏览器默认右键菜单.a标签默认连接跳转...,如何阻止呢? Firefox中,event必须作为参数传入.  IE中,event是window对象的属性. ev ...

  4. 一次部署HTTPS的相关事件引发的思考

    前言: 上周五快要下班的时候,突然收到通知客户希望了解一下部署HTTPS的流程,这种事情谁听了都会有几分诧异的.因为这件事虽然和工作有一定的相关度,但平时不会走这个方向,实际上也较少接触.此外,客户手 ...

  5. .Net中使用SendGrid Web Api发送邮件(附源码)

    SendGrid是一个第三方的解决邮件发送服务的提供商,在国外使用的比较普遍.国内类似的服务是SendCloud.SendGrid提供的发送邮件方式主要是两种, 一种是SMTP API, 一种是Web ...

  6. SQL*Plus环境变量设置浅析

    SQL*Plus的使用环境是可以通过login.sql 或 glogin.sql脚本来设置的,可能很多初学者或不习惯使用SQL*Plus的老鸟都不知道.因为在如今UI工具(Toad.PL/SQL De ...

  7. Oracle数据库shutdown immediate被hang住的几个原因

    实验操作环境:         操作系统:Red Hat Enterprise Linux ES release 4 (Nahant Update 6)                         ...

  8. javascript-装饰者模式

    装饰者模式笔记 在不改变原对象的基础上, 通过对其进行包装拓展(添加属性或方法)使原有对象可以满足用户的更复杂要求. 需求不是一成不变的,需求会不断改进,以增强用户体验 demo实例:对输入框添加fo ...

  9. Python 常用模块之time&datetime 和random

    本节大纲: 模块介绍 time &datetime模块 random 一.模块介绍: 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他 ...

  10. 在Windows Server 2012 R2中搭建SQL Server 2012故障转移集群

    需要说明的是我们搭建的SQL Server故障转移集群(SQL Server Failover Cluster)是可用性集群,而不是负载均衡集群,其目的是为了保证服务的连续性和可用性,而不是为了提高服 ...