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);
            }


     完整代码


  • 相关阅读:
    hlgoj 1766 Cubing
    Reverse Linked List
    String to Integer
    Bitwise AND of Numbers Range
    Best Time to Buy and Sell Stock III
    First Missing Positive
    Permutation Sequence
    Next Permutation
    Gray Code
    Number of Islands
  • 原文地址:https://www.cnblogs.com/shenba/p/1626898.html
Copyright © 2011-2022 走看看