`
saybody
  • 浏览: 904071 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

解析Html生成标签树(一)

阅读更多

解析Html成标签树结构以后,我们不但可以很容易取得想要的元素,同时也很容易将Html转换成对应的XML文件。但是由于代码是在公司写的,所以没有粘贴出来的可能性,所以我只能给出大概的代码流程,具体细节描述,相信各位都很容易写出来,并且写的比我好,关键的是算法实现思想。算法的关键如下:

1. Html中每个tag都是都将作为树中的一个节点存在的,每个tag都属于树中的某一层。
2. 辅助数据结构:栈(stack)、List、HashTable。其中HashTable[i](i属于int类型)是一个List,用于临时存储第i层子Tag。
3. 顺序扫描Html文本,当遇到”<A~Z”这样的标志,表示可能是一个Tag,调用GetTag()函数对此段代码进行解析,解析出Tag名,Tag属性等等。如果返回值不为空,那么将返回值入栈。并且记录次tag的开始位置。
4. 遇到</A~Z>这样的标志,表示可能是某个Tag的结束。解析出此结束标志的Tag名。如果在栈中找到与此结束标志名同名的元素(此元素属于栈中第iLevel层),那么表示找到匹配的Tag。则Tag出栈,将HashTable[iLevel+1]到HashTable[maxLevel]中的所有元素取出作为此Tag的子节点。放入第HashTable [iLevel]中。并记录Tag的结束位置。
5. 对于<Tag>xxx</Tag>之间的字符串xxx,将其作为特殊的HtmlTextTag处理。出栈,和入栈操作与普通Tag类似。
6. 当栈为空的时候表示最后一次出栈的Tag给根节点。 由于是在公司内部开发的东西,所以不可能把源代码拿出来粘贴,所以只能把大概的代码给出。
伪代码如下:
public void Parse()

{

    char ch = GetCurrentChar();  //取第一个字符   

    while (!Eof())

    {

        if (ch == '<')

        {

            ch = MoveNext();     //取下一个字符   

            if ((ch >= 'A') && (ch <= 'Z') || (ch == '!'))

            {

                iBeginPos = Index;       //记录开始位置

                //表示可能是一个标签 

                HtmlTag tag = GetTag();  //解析此Tag   

                if (tag != null)

                {

                    //首先判断是否有文本   

                    if (m_CurrentText.Lenght > 0)

                    {

                        //将文本作为一个普通Tag入栈   

                        Stack.Push(new HtmlTextTag(m_CurrentText));

                    }

                    tag.BeginPos = iBeginPos;   //记录此Tag的开始位置   

                    Stack.Push(tag);            //把Tag入栈   

                }

            }



            ch = GetCurrentChar();

            if (ch == '/')

            {

                //可能是结束标签   

                tagName = GetTagName();

                //从上到下查看Stack,如果Tag中存在   

                if (FindInStack(tagName))

                {

                    //在栈中找到名为tagName的元素,则把找到的元素出栈   

                    PopTag(tagName);

                }

            }

        }

        else

        {

            //对于<AAA>xxx</AAA>之间的文本xxx,这里将作为TextTag来处理  

            m_CurrentText.Append(GetCurrentChar());

        }

        //继续处理下一个字符   

        ch = MoveNext();

    }



    //解析完成以后,如果栈不空,那么把元素出栈,并把最后一次出栈的元素作为根   

    if (Stack.Count > 0)

    {

        HtmlTag tag = null;

        while (Stack.Count > 0)

        {

            tag = Stack.Pop();

            PopTag(tag);

        }



        //最后一个元素作为根元素   

        if (tag != null)

        {

            m_listRoot.Add(tag);

        }

    }

}



private void PopTag(HtmlTag tag)

{

    int iLevel = Stack.Count;



    //找到了元素,把iLevel到m_IMaxLevel中所有的元素按照全部作为tag的子元素   

    for (int i = iLevel + 1; i < m_iMaxLevel; i++)

    {

        for (j = 0; j < HashTable[i].Count; j++)

        {

            tag.Children.Add(HashTable[i][j]);

        }

    }



    //表示栈已经为空,那么最后一次出栈的tag将作为根   

    if (Stack.Count == 0)

    {

        m_listRoot.Add(tag);

    }

}



private void PopTag(string tagName)

{

    /*

     * 元素出栈的时候,首先需要把当前已经存在了的HtmlTextTag入栈

     * 比如:<A>文本段1<B>文本段2</B>文本段3</A>

     * 在Parse中,当解析出<B>入栈前,需要先把"文本段1"入栈

     * 在这里,解析出了</B>结束标志

     * 那么首先需要把"文本段2"入栈。

     * 解析出</A>则需要把"文本段3'入栈。

     * 这样才能够保证"文本段1"和"文本段3"成为<A>的子节点,而"文本段2"作为<B>的子节点

     */

    if (m_CurrentText.Lenght > 0)

    {

        //将文本作为一个普通Tag入栈   

        Stack.Push(new HtmlTextTag(m_CurrentText));

    }



    HtmlTag tag = Stack.Pop();  //元素出栈   

    int iLevel = Stack.Count;   //记录栈元素数   



    while (tag.Name != tagName)

    {

        //将tag放入第iLevel层的List中   

        HashTable[iLevel].Add(tag);

        tag = Stack.Pop();

        iLevel = Stack.Count;

    }



    //元素出栈后续处理   

    PopTag(tag);

}



private HtmlTag GetTag()

{

    if ("如果发现是 < !--开头的元素") //则表示是注释   

    {

        SkipComment();

    }



    HtmlTag tag = new HtmlTag();

    tag.Name = GetTagName();

    //这里的Attribute我将其作为HashTable类型,Hash[属性名]=属性值   

    tag.Attribute = GetTagAttribute();

    return tag;

} 

解析结束以后,通过访问m_listRoot就可以遍历出所有的节点了。上面仅仅是给出了大概的方法,不过我相信要将上面的方法转换成可运行代码,各位都是有这个能力的。。。

分享到:
评论

相关推荐

    js 解析 json 生成树

    在JavaScript中,解析JSON并生成树形结构是一种常见的需求,特别是在构建前端应用或者处理层级数据时。本示例中提到的“js 解析 json 生成树”是一个将JSON数据转换为可交互的树形结构的过程。这个过程通常涉及到...

    解析带有html标签的json数据

    HTML json parser通常会先将JSON数据中的HTML字符串提取出来,然后使用HTML解析器来解析这些标签,将其转换为结构化的DOM(Document Object Model)树。 在实际应用中,我们可能会遇到以下几种情况: 1. **提取纯...

    一个非常好的js解析xml生成一个tree

    标题中的“一个非常好的js解析xml生成一个tree”指的是使用JavaScript编程语言将XML(可扩展标记语言)数据转换为树形结构。在Web开发中,XML常用于存储和传输结构化数据,而JavaScript作为客户端脚本语言,可用于...

    C#获取HTML源码及生成DOM树

    总的来说,"C#获取HTML源码及生成DOM树"涉及的关键技术包括:使用`HttpClient`进行网络请求,`HtmlAgilityPack`库解析HTML并构建DOM,以及通过DOM树进行网页元素的查找和操作。这些技能对于开发爬虫、自动化测试、...

    jquery动态生成树

    本示例代码“jquery动态生成树”是关于如何利用jQuery和相关技术,如Struts2、treeview插件及JSON数据格式,来动态地在网页上构建一个可交互的目录树结构。 首先,让我们详细了解一下每个组件的作用: 1. **jQuery...

    c++ html dom 树

    首先,C++ HTML DOM树是通过解析HTML源代码来创建的一个数据结构,它以树的形式表示了HTML文档的各个元素。每个节点代表HTML中的一个元素,如`&lt;html&gt;`, `&lt;head&gt;`, `&lt;body&gt;`等,甚至包括文本节点和注释。这种树形结构...

    CMS标签解析入门示例

    5. **内容替换**:解析器将获取的数据替换掉模板中的标签,生成最终的HTML输出,然后发送给客户端浏览器。 对于嵌套标签,情况会稍微复杂一些。嵌套标签是指一个标签内包含另一个或多个标签,这在处理复杂逻辑或...

    dTree 生成无限级树形菜单

    在网页开发中,树形菜单是一种常见的用户界面元素,它能有效地组织和展示层次结构的信息。`dTree` 是一个JavaScript对象,专用于构建无限级的树形菜单。本篇文章将深入探讨如何利用`dTree`来生成动态的树形菜单,并...

    文件目录生成html 把WORD转HTML

    8. **自动化工具**:描述中提到的小工具就是一种自动化解决方案,它可以读取Word文档,解析其结构,然后生成HTML代码。这样的工具通常需要使用编程语言(如Python、Java或C#)编写,利用库(如Python的`python-docx`...

    读取xml生成树,ajax读取xml动态生成树(1)

    总结来说,通过理解XML的基本结构,利用DOM解析XML并构建树形结构,结合AJAX实现异步数据加载,我们能够动态生成交互式的树形菜单。在实际应用中,这样的技术可以用于网站导航、文件系统浏览、数据展示等多种场景,...

    jsp+dtree+taglib 动态生成树节点

    本项目结合了JSP(JavaServer Pages)、dTree(一个JavaScript实现的树形菜单库)以及Taglib(自定义标签库),提供了一种高效的方法来实现在服务器端动态生成树结构并传递到客户端展示。 首先,JSP是Java的一种...

    JQuery实例动态生成树

    在JavaScript文件中,会解析这个JSON数据,然后调用适当的jQuery方法来生成和操作树形结构。 总之,jQuery动态生成树形结构涉及HTML结构、JSON数据处理、事件绑定以及可能的异步加载。通过熟练掌握这些技能,开发者...

    QT基于HTML生成WORD文件

    在HTML生成Word文件的过程中,我们首先需要创建一个QTextDocument实例,然后利用QTextDocument的fromHtml()方法,将HTML字符串解析成QTextDocument对象。这样,HTML中的各种标记将被转换为相应的文本格式。 HTML是...

    java将markdown文档转换成html,生成左侧目录

    本项目的目标是创建一个工具,它能够将Markdown文档转换为HTML格式,并且生成带有左侧目录的页面布局。这样的设计非常适合阅读长篇的技术文档或者教程,因为用户可以通过左侧目录快速跳转至不同章节,提高阅读和导航...

    jsp动态生成目录树

    5. **展示结果**:当用户请求JSP页面时,服务器执行上述逻辑,生成HTML和JavaScript代码,返回给浏览器,浏览器解析并执行JavaScript,从而在页面上显示目录树。 在提供的文件名`JSP与树型菜单--diegoyun`中,可能...

    百度网盘目录树生成器v2.0版本

    标题“百度网盘目录树生成器v2.0版本”涉及到的是一个专为百度网盘设计的工具,其主要功能是帮助用户生成网盘内的目录树结构。这个工具是基于Python编程语言编写的,并且已经打包为Windows可执行文件(exe),方便在...

    java 读取html过滤标签

    Java中可以使用`javax.xml.parsers.DocumentBuilderFactory`和`org.w3c.dom.Document`来解析HTML。DOM解析器将整个HTML文档加载到内存中形成一个树形结构。然后,我们可以遍历这个结构,找到并过滤掉特定标签。例如...

    ajax动态生成树 用于jsp

    标签"ajax的动态树的生成代码"提示我们在服务器端(这里是JSP)需要生成树的数据。这通常涉及到数据库查询或者静态数据的读取。例如,使用Java的Servlet或JSP内置对象来处理请求: ```jsp ;charset=UTF-8" ...

    项目中使用到的解析html富文本

    在项目中,解析HTML富文本能够确保内容在不同平台和设备上保持一致的展示效果,提高用户体验。 三、富文本解析库与工具 1. JavaScript:在Web前端,常用的富文本解析库有TinyMCE、CKEditor、Quill等。它们提供了...

    八种树形js标签

    3. **AST(抽象语法树)**:当JS代码被解析时,会生成一个抽象语法树,表示代码的结构。开发者可以利用AST进行代码分析、转换和优化,例如Babel等工具就是基于AST来实现ES6+到ES5的转换。 4. **二叉树**:二叉树是...

Global site tag (gtag.js) - Google Analytics