zoukankan      html  css  js  c++  java
  • C#使用Linq to XML进行XPath查询

    最近在用到HtmlAgliltyPack进行结点查询时,发现这里选择结点使用的是XPath。所以这里总结一下在C#中使用XPath查询XML的方法。习惯了用Linq,这里也是用的Linq to xml的。

    Linq To XML的核心类是XDocumentXElementXAttribute,需要引用using System.Xml.Linq命名空间。

    这三个类简单理解为:

    XDocument:打开的整个XML文档

    XElement:节点元素

    XAttribute:属性

    下面简单介绍一下使用

    如有以下XML文件

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <html>
     3   <head>
     4     <title>测试XML</title>
     5   </head>
     6   <body>
     7     <div class="card-container">
     8       <div class="item-title">
     9         <h3 class="item-shop-name">汪家羊肉馆</h3>
    10       </div>
    11       <div class="item-comment">
    12         <span class="price1">¥62/人</span>
    13         <span class="price2">¥12/人</span>
    14         <span class="price3">2</span>
    15         <span class="price4">12</span>
    16       </div>
    17     </div>
    18   </body>
    19 </html>

    打开XML文件

    1 XDocument doc = XDocument.Load("demo.xml");

    获取根节点(html节点 返回XElement类型)

    var root = doc.Root;

    获取第一个子节点(返回XElement类型)

    1 var firstNode = root.FirstNode;

    获取全部子节点(返回IEnumerable<XNode>)

    1 var allChildNode = root.Nodes();

    获取指定名称的第一个子节点(返回XElement类型)

    1 var headNode = root.Element("head");

    获取指定名称的全部子节点(返回IEnumerable<XElement>)

    var allNamedNode = root.Elements("head");

    获取节点指定名称的属性(<div class="card-container"> )

    1 var attribute = root.Element("body").Element("div").Attribute("class");

    获取节点的全部属性

    1  var allAttributes = root.Attributes();

    使用XPath查询(需要引用using System.Xml.XPath命名空间)

    1 var xpathQeury = root.XPathSelectElement("body/div");

    获取节点的名称和值

    1   //获取结点的名称
    2    var nodeName = root.Name;
    3    //获取节点的值
    4    var nodeValue = root.Value;

    保存XML

    1 doc.Save("demo.xml");

    Linq查询(获取<span class="price2">¥12/人</span>节点下的值)

    这里仅做示例,返回返回IEnumerable<XElement>类型的都可以进行Linq查询

    不使用XPath

    1 var queryResult = root.Element("body").Element("div").Elements("div").ElementAt(1).Elements("span").Where(x=>x.Attribute("class") != null && x.Attribute("class").Value == "price2").FirstOrDefault();
    2             if(queryResult != null)
    3                 Console.WriteLine(queryResult.Value);

    使用XPath

    1 var xpathQueryResult = root.XPathSelectElements("body/div/div[2]/span").Where(x => x.Attribute("class") != null && x.Attribute("class").Value == "price2").FirstOrDefault();
    2             if(xpathQueryResult != null)
    3                 Console.WriteLine(xpathQueryResult.Value);

    输出结果都为下

    下面开始介绍XPath

    XPath 是 XML 文档中查找信息的语言,使用XPath可以对XML的元素进行查找。

    这里重着介绍一下XPath语法

    /    从根节点开始选择

    1 var xpathRoot = doc.XPathSelectElement("/html");
    2 var xpathRoot2 = doc.XPathSelectElement("html");

    运行结果

    //   获取文档中所有指定的结点,不管它的位置

    如要获取xml文档中所有的span节点

    1             //以下获取的结果都是一样的
    2             //尽管位置不一样,但查询结果是一样的
    3             var body = root.Element("body").Element("div").Elements("div").ElementAt(1);
    4             var allDivNodeInBody = body.XPathSelectElements("//div");
    5             var allDivNodeInDoc = doc.XPathSelectElements("//div");
    6             Console.WriteLine(allDivNodeInBody.Count());
    7             Console.WriteLine(allDivNodeInDoc.Count());

    运行结果

    .   当前节点

    1  var currentNode = root.XPathSelectElement(".");
    2         

    运行结果

    ..  当前节点的父节点

    1 var parentNode = root.Element("body").XPathSelectElement("..");

    运行结果

    @  选取属性

    这个操作在Linq to xml里不支持,会产生一个"XPath 表达式的计算结果为意外类型 System.Xml.Linq.XAttribute。"异常

    通配查询

    *     全部节点

    @*  全部属性(不支持)

    谓词查询

    选择第一个查询结果,如<span class="price1">¥62/人</span>

    //span[1]
    1 var firstSpanNode = doc.XPathSelectElement("//span[1]");

    运行结果

    选择最后一个查询结果,如最后一个<span class="price4">12</span>

    //span[last()]
    1  var lastDivNode = doc.XPathSelectElement("//span[last()]");
    2 Console.WriteLine(lastDivNode.Attribute("class").Value);

    运行结果

    选择带有属性class的div节点

    //div[@class]
    1 var nodeWithClassAttribute = doc.XPathSelectElements("//div[@class]");
    2             foreach (var item in nodeWithClassAttribute)
    3             {
    4                 Console.WriteLine("====================");
    5                 Console.WriteLine(item);
    6             }

    运行结果

    选择带有属性class,且值为item-title的div节点

    //div[@class='item-title']
    1  var nodeWithClassValueAttribute = doc.XPathSelectElements("//div[@class='item-title']");
    2             foreach (var item in nodeWithClassValueAttribute)
    3             {
    4                 Console.WriteLine(item);
    5             }

    运行结果

    简单的选择计算

    获取倒数第二个div节点

    //div[last()-1]
    1 var nextToLastDivNode = doc.XPathSelectElement("//div[last()-1]");

    运行结果

    获取值大于10的span节点

    //span[text()>10]
    1 var greaterThanTenSpan = doc.XPathSelectElements("//span[text()>10]");

    运行结果:

    获取值加10等于22的span节点

    //span[text()+10=22]
    1 var plusTenSpan = doc.XPathSelectElements("//span[text()+10=22]");

    运行结果:

    常用运行符如下

    +               加

    -                减

    *               乘

    div           除

    =              等于

    !=             不等于

    >              大于

    <              小于

    >=           大于等于

    <=            小于等于

    or            或

    and          与

    组合查询

    如查询值等于12或等于2的span节点

    //span[text()=2]|//span[text()=12]
    1  var combineQuery = doc.XPathSelectElements("//span[text()=2]|//span[text()=12]");
    2             foreach (var item in combineQuery)
    3             {
    4                 Console.WriteLine(item.Value);
    5             }

    运行结果

    示例代码

    参考:

    https://www.w3.org/TR/2017/REC-xpath-31-20170321/

    https://www.w3school.com.cn/xpath/index.asp

    life runs on code

    作者: zhaotianff

    转载请注明出处

  • 相关阅读:
    转载cocos3.17cmake打包
    cocos-lua3.17 Lua tableView工具类
    cocso引擎整体流程
    letCode-1
    letCode-2
    图像语义分割的前世今生
    简要介绍弱监督学*
    win10下乌龟git安装和使用
    STM32F4+Wi-Fi+EDP 向 OneNet 上传数据
    GoogLeNet学习
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/11319871.html
Copyright © 2011-2022 走看看