C#中利用Markup Service实现HTML解析为DOM Tree
2024-08-26 00:15:32
供稿:网友
一个轻量级parsing 实现。这个代码不会从网上下载任何资料,也不会执行任何脚本,纯属parsing。
parsing是通过mshtml的markup service实现的。要正确使用这个代码,需要添加mshtml引用。
由于.net中没有定义ipersiststreamint接口,就必须自己实现,接口定义:
以下内容为程序代码:
[comvisible(true), comimport(), guid("7fd52380-4e07-101b-ae2d-08002b2ec713 " ) , interfacetypeattribute(cominterfacetype.interfaceisiunknown)]
public interface ipersiststreaminit
{
void getclassid([in, out] ref guid pclassid);
[return: marshalas(unmanagedtype.i4)] [preservesig]
int isdirty();
void load([in, marshalas(unmanagedtype.interface)] ucomistream pstm);
void save([in, marshalas(unmanagedtype.interface)] ucomistream pstm,
[in, marshalas(unmanagedtype.i4)] int fcleardirty);
void getsizemax([out, marshalas(unmanagedtype.lparray)] long pcbsize);
void initnew();
}
以下内容为程序代码:
unsafe ihtmldocument2 parse(string s)
{
ihtmldocument2 pdocument=new htmldocumentclass();
if(pdocument!=null)
{
ipersiststreaminit ppersist=pdocument as ipersiststreaminit ;
ppersist.initnew();
ppersist=null;
imarkupservices ms=pdocument as imarkupservices ;
if(ms!=null)
{
imarkupcontainer pmc=null;
imarkuppointer pstart,pend;
ms.createmarkuppointer(out pstart);
ms.createmarkuppointer(out pend);
stringbuilder sb=new stringbuilder(s);
intptr psource=marshal.stringtohglobaluni(s);
ms.parsestring(ref *(ushort*)psource.topointer(),0,out pmc,pstart,pend);
if(pmc!=null)
{
marshal.release(psource);
return pmc as ihtmldocument2;
}
marshal.release(psource);
}
}
return null;
}
写代码的时候出了一点问题,imarkupservice::parsestring第一个参数是ref ushort,显然要传入html代码,这个ushort必须是第一个widechar了,所以这里通过使用不安全代码来绕过编译器警告。