给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

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

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

关键代码

给xpath添加正则表达式匹配函数 实现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 " 1 2 new
        XPathResultType[] { XPathResultType.NodeSet, XPathResultType.String }, XPathResultType.Boolean);
                    
break ;
                
//  去除空格
                 case   " Trim " :
                    func 
=   new  XPathExtensionFunction( " Trim " 1 1 ,
                        
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 ;
            }
        }
    }
给xpath添加正则表达式匹配函数 实现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);
        }


 完整代码


 

 

 

 

 

 

你可能感兴趣的:(正则表达式)