zoukankan      html  css  js  c++  java
  • 给xpath添加正则表达式匹配函数

      做网页解析时,将html转成xml格式之后,再利用xpath则可以轻易地截取任何所需要的数据。在使用xpath时,常常会用到其中的一些函数,特别是字符串函数,完整的函数列表可在w3school找到:http://www.w3school.com.cn/xpath/xpath_functions.asp#string)。然而这仅仅是标准xpath里所提供的,dotnet里这只实现了一部分,特别是本标题所提到的正则匹配函数fn:matches(string,pattern),dotnet里竟然不支持。虽然dotnnet里还是能用诸如contains等判断函数,但比起强大的正则表达式,其实现的功能远远不能满足要求。

      为了能够更加灵活、方便的匹配字符串,需要给xpath添加自定义的正则匹配函数,幸好dotnet提供了接口,先看看这些基类及接口。

      XsltContext

      封装可扩展样式表转换语言 (XSLT) 处理器的当前执行上下文,使 XML 路径语言 (XPath) 在 XPath 表达式中解析函数、参数和命名空间。需要定义一个继承XsltContext的子类,实现对自定义函数的调用。

      IXsltContextFunction

      为在运行库执行期间在可扩展样式表转换语言 (XSLT) 样式表中定义的给定函数提供一个接口。实现该接口的子类定义以及提供自定义函数的功能。

      IXsltContextVariable

    为在运行库执行期间在样式表中定义的给定变量提供一个接口。其子类实现在调用自定义函数时,参数值的计算。

       涉及类比较多,但是在具体实现远没有那么复杂,后续添加其他函数也很方便。

    关键代码

    实现XsltContext
    public class XpathContext : XsltContext
        {
            
    // XsltArgumentList to store my user defined variables
            private XsltArgumentList m_ArgList;
            
    // Constructors 
            public XpathContext()
            { }
            
    public XpathContext(NameTable nt)
                : 
    base(nt)
            {
            }
            
    public XpathContext(NameTable nt, XsltArgumentList argList)
                : 
    base(nt)
            {
                m_ArgList 
    = argList;
            }
            
    // Returns the XsltArgumentList that contains custom variable definitions.
            public XsltArgumentList ArgList
            {
                
    get
                {
                    
    return m_ArgList;
                }
            }
            
    // Function to resolve references to my custom functions.
            public override IXsltContextFunction ResolveFunction(string prefix,
         
    string name, XPathResultType[] ArgTypes)
            {
                XPathExtensionFunction func 
    = null;
                
    // Create an instance of appropriate extension function class.
                switch (name)
                {
                    
    // 匹配正则表达式, XPath1.0没有该方法
                    case "Match":
                        func 
    = new XPathExtensionFunction("Match"12new
            XPathResultType[] { XPathResultType.NodeSet, XPathResultType.String }, XPathResultType.Boolean);
                        
    break;
                    
    // 去除空格
                    case "Trim":
                        func 
    = new XPathExtensionFunction("Trim"11,
                            
    new XPathResultType[] { XPathResultType.String }, XPathResultType.String);
                        
    break;
                    
    default:
                        
    throw new ArgumentException("没有定义" + name + "函数");
                }

                
    return func;
            }

            
    // Function to resolve references to my custom variables.
            public override IXsltContextVariable ResolveVariable(string prefix, string name)
            {
                
    // Create an instance of an XPathExtensionVariable.
                XPathExtensionVariable Var;
                Var 
    = new XPathExtensionVariable(name);
                
    return Var;
            }
            
    public override int CompareDocument(string baseUri, string nextbaseUri)
            {
                
    return 0;
            }
            
    public override bool PreserveWhitespace(XPathNavigator node)
            {
                
    return true;
            }
            
    public override bool Whitespace
            {
                
    get
                {
                    
    return true;
                }
            }
        }
    实现IXsltContextFunction
        /// <summary>
        
    /// 自定义正则表达式函数
        
    /// </summary>
        public class XPathExtensionFunction : IXsltContextFunction
        {
            
    private XPathResultType[] m_ArgTypes;
            
    private XPathResultType m_ReturnType;
            
    private string m_FunctionName;
            
    private int m_MinArgs;
            
    private int m_MaxArgs;
            
            
    /// <summary>
            
    /// 获取函数的参数的最小数目。这使用户能够区分重载函数
            
    /// </summary>
            public int Minargs
            {
                
    get
                {
                    
    return m_MinArgs;
                }
            }

            
    /// <summary>
            
    /// 获取函数的参数的最大数目。这使用户能够区分重载函数
            
    /// </summary>
            public int Maxargs
            {
                
    get
                {
                    
    return m_MaxArgs;
                }
            }

            
    /// <summary>
            
    /// 获取为函数的参数列表提供的 XML 路径语言 (XPath) 类型。该信息可用于发现函数的签名,该签名使您能够区分重载函数
            
    /// </summary>
            public XPathResultType[] ArgTypes
            {
                
    get
                {
                    
    return m_ArgTypes;
                }
            }

            
    /// <summary>
            
    /// 获取 XPathResultType,它表示函数返回的 XPath 类型
            
    /// </summary>
            public XPathResultType ReturnType
            {
                
    get
                {
                    
    return m_ReturnType;
                }
            }

            
    /// <summary>
            
    /// 创建自定义函数的实例
            
    /// </summary>
            
    /// <param name="name">方法名称</param>
            
    /// <param name="minArgs">最小参数个数</param>
            
    /// <param name="maxArgs">最大参数个数</param>
            
    /// <param name="argTypes">参数类型数组</param>
            
    /// <param name="returnType">返回类型</param>
            public XPathExtensionFunction(string name, int minArgs, int maxArgs, XPathResultType[] argTypes, XPathResultType returnType)
            {
                m_FunctionName 
    = name;
                m_MinArgs 
    = minArgs;
                m_MaxArgs 
    = maxArgs;
                m_ArgTypes 
    = argTypes;
                m_ReturnType 
    = returnType;
            }

            
    // 在运行时调用
            public object Invoke(XsltContext xsltContext, object[] args, XPathNavigator docContext)
            {
                
    // The two custom XPath extension functions
                switch (m_FunctionName)
                {
                    
    case "Match":
                        
    // 调用正则匹配 参数一为正则表达式
                        return Regex.IsMatch(docContext.InnerXml, args[0].ToString());
                    
    case "Trim":
                        
    return docContext.Value.Trim();
                    
    default:
                        
    throw new ArgumentException("没有定义" + m_FunctionName + "函数");
                }
            } 
        }

    具体调用(代码中连接来源于国家旅游局)

    static void Main(string[] args)
            {
                
    string xml = @"
                <links>
                <a  href=""http://www.cnta.gov.cn/html/2009-12/2009-12-3-16-30-23909.html"">2009年1-9月主要城市接待情况(二)</a>
                <br/>
                <a href=""http://www.cnta.gov.cn/html/2009-10/2009-10-16-10-2-71826.html"">2009年1-8月主要城市接待情况(二)</a>            
                <br/>
                <a href=""http://www.cnta.gov.cn/html/2009-10/2009-10-16-10-2-71826.html"">2009年1-8月主要城市接待情况(二)</a>
                </links>
    ";

                XmlDocument doc 
    = new XmlDocument();
                doc.LoadXml(xml);

                XpathContext xpathContext 
    = new XpathContext();

                XmlNode node 
    = doc.SelectSingleNode(@"//a[Match('\d{4}年\d{1,2}-\d{1,2}月主要城市接待情况\(二\)')]", xpathContext);

                Console.WriteLine(node.Attributes[
    "href"].Value);
            }


     完整代码


  • 相关阅读:
    easyui-datagrid 编辑模式下保存数据,光标所在单元格无法保存。
    esayui datebox 系统日期之后禁止选择
    使用easy-TreeGrid完成角色权限设置;使用checkbox
    jquery easyui easyui-combobox 与easyui-textbox 取值赋值操作
    原生js table中点击操作按钮,获取相应行某列需要的值作为参数请求跳转
    excel 导出 兼容到ie (JavaScript)
    vue 路由导航重复跳转报错解决记录
    变量提升
    定时器轮播,轮播一次加载一张图;
    es7 es8 新加的特性。
  • 原文地址:https://www.cnblogs.com/shenba/p/1626898.html
Copyright © 2011-2022 走看看