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

前言: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一般是由引用服务时代理对象去解析的。但如果真的有这么变态的需求我们也不用担心了。在此记录下,以后如果大家遇到希望能节约大伙的时间。

时间: 2024-11-24 10:22:49

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

dom4j解析Xml,dom4j解析带命名空间的Xml内容,dom4j解析xml为实体类

首先引入maven: <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</arti

linq 解析 带命名空间的xml

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

带命名空间的XML的dom4j应用&lt;转&gt;

Element root = document.getRootElement();     List   recordenvlist = document.selectNodes("//gml:envelope");     //gml:envelope 提示 NoClassDefFoundError org.dom4j.DocumentFactory.createXPath 原因:dom4j的xpath api依赖jaxen完成解决方法:在系统中加入jaxen.jar.jaxen.j

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

文件内容如下 <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://WebXml.com.cn/"> <string>浙江</string> <string>杭州</string> <

C#基础巩固(3)-Linq To XML 读取XML

记录下一些读取XML的方法,以免到用的时候忘记了,还得花时间去找. 一.传统写法读取XML 现在我有一个XML文件如下: 现在我要查找名字为"王五"的这个人的 Id 和sex(性别) 和age(年龄) 代码: static void Main(string[] args) { XDocument xdoc = XDocument.Load("4.xml"); //加载xml List<XElement> eles = new List<XEleme

C# 解析带命名空间的xml

xml <?xml version="1.0" encoding="utf-8"?> <string xmlns="http://tempuri.org/">发票代码:012001800311 发票号码:24961816 开票日期:2019-04-02 购方企业名称:购方纳税号:913101140781x22VV1 销方企业名称:清出公司 销方纳税号:911201163409833307 价税合计:4 金额:94.76 税

c#读取写XML

c#读取XML XML文件是一种常用的文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场所都有它的身影.Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具.XML是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立,虽然XML占用的空间比二进制数据要占用更多的空间,但XML极其简单易于掌握和使用.微软也提供了一系列类库来倒帮助我们在应用程序中存储XML文件.

XML(1)——shema约束之命名空间

一.XML的两种约束DTD和Schema摘自IBM官网一段话:"XML DTD(XML的文档类型定义)是近几年来XML技术领域所使用的最广泛的一种模式.但是由于XML DTD并不能完全满足XML自动化处理的要求,例如不能很好实现应用程序不同模间的相互协调,缺乏对文档结构.属性.数据类型等约束的足够描述等等,所以W3C于2001年5月正式推荐XML Schema为XML 的标准模式.显然,W3C希望以XML Schema来作为XML模式描述语言的主流,并逐渐代替XML DTD".可见Sc

两种读取微信xml消息的方式比较

直接贴代码和结果. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Serialization; using System.IO; using System.Diagnostics; namespace ConsoleApplication_xm