Java解析HTML标签Tag

import java.util.HashMap;
import java.util.Map;

public class TagParser {
	private Integer index = 0;
	private char[] tagChar;
	private int position = 0;
	/* 解析符号 */
	private char symbol = '"';
	public static final String START_SCRIPT = "<script";
	public static final String END_SCRIPT = ">";
	public static final String END_SCRIPT_1 = "/>";
	public static final String EQ = "=";
	public static final char SPACE = ' ';
	public static final String MUST_SPACE = " ";
	public static final String TAB = "	";
	public static final String SYMBOL = "'";
	private DFAStatus status;
	private Map<Integer, Entity> map = new HashMap<Integer, Entity>();
	private Map<String, String> result = new HashMap<String, String>();

	public static void main(String[] args) throws SymbolError {
		String tag = "<script filter=\"a\'\" type=\"text/javascript\" id='node' src=\"http://www.test.com/abc.js\" async=\"true\" />";
		int i = 0;
		long start = System.currentTimeMillis();
		while (i < 10) {
			TagParser token = new TagParser(tag);
			token.parser();
			System.out.println(token.getAttr("src"));
			i++;
			System.out.println(token);
		}
		System.out.println("use time:" + (System.currentTimeMillis() - start));
	}

	private boolean startsWith(String str) {
		char[] chat = str.toCharArray();
		if (position + chat.length > tagChar.length) {
			return false;
		}
		for (int i = 0; i < chat.length; i++) {
			if (tagChar[position + i] != chat[i]) {
				if (is_az(chat[i])) {
					if (tagChar[position + i] == chat[i] - 32) {
						continue;
					}
				}
				return false;
			}
		}
		return true;
	}

	public void parser() throws SymbolError {
		if (status == null) {
			status = DFAStatus.UNSTART;
			skipSpace();
		}
		if (status == DFAStatus.UNSTART) {
			if (startsWith(START_SCRIPT)) {
				position += START_SCRIPT.length();
				status = DFAStatus.START;
				parser();
			} else {
				throw new SymbolError("语法错误:" + tagChar[position]);
			}
		} else if (status == DFAStatus.START) {
			nextSpace();
			parser();
		} else if (status == DFAStatus.NULL) {
			skipSpace();
			if (startsWith(END_SCRIPT_1)) {
				status = DFAStatus.DONE;
				done();
				return;
			} else if (startsWith(END_SCRIPT)) {
				status = DFAStatus.DONE;
				done();
				return;
			}
			parserName();
			parser();
		} else if (status == DFAStatus.EQ) {
			parserVal();
			parser();
		} else if (status == DFAStatus.SYMBOL_END) {
			status = DFAStatus.NULL;
			parser();
		}
	}

	private void done() {
		for (Entity entity : map.values()) {
			result.put(entity.name, entity.value);
		}
	}

	private void parserVal() throws SymbolError {
		skipSpace();
		StringBuilder builder = new StringBuilder();
		int startIndex = position;
		for (int i = position; i < tagChar.length; i++) {
			if (i == startIndex) {
				if (tagChar[i] == '\'' || tagChar[i] == '"') {
					symbol = tagChar[i];
					status = DFAStatus.SYMBOL_START;
					position++;
				} else {
					throw new SymbolError("语法错误:" + tagChar[position]);
				}
			} else {
				if (tagChar[i] == symbol) {
					status = DFAStatus.SYMBOL_END;
					position++;
					break;
				} else {
					builder.append(tagChar[i]);
					position++;
				}
			}
		}
		map.get(index).value = builder.toString();
		index++;
	}

	private boolean is_AZ(char chat) {
		return chat >= 65 && chat <= 90;
	}

	private boolean is_az(char chat) {
		return chat >= 97 && chat <= 122;
	}

	private void parserName() throws SymbolError {
		StringBuilder builder = new StringBuilder();
		for (int i = position; i < tagChar.length; i++) {
			if (is_az(tagChar[i]) || is_AZ(tagChar[i])) {
				builder.append(tagChar[i]);
				position++;
			} else {
				if (builder.length() > 0) {
					skipSpace();
					nextEQ();
					break;
				}
			}
		}
		if (builder.toString().length() == 0) {
			throw new SymbolError("语法错误:" + tagChar[position]);
		}
		map.put(index, new Entity(builder.toString()));
	}

	private void nextEQ() throws SymbolError {
		if (startsWith(EQ)) {
			position++;
			status = DFAStatus.EQ;
		} else {
			throw new SymbolError("语法错误:" + tagChar[position]);
		}
	}

	private void skipSpace() {
		for (int i = position; i < tagChar.length; i++) {
			if (tagChar[i] == SPACE || tagChar[i] == '\t') {
				position++;
			} else {
				return;
			}
		}
	}

	private void nextSpace() throws SymbolError {
		if (startsWith(MUST_SPACE)) {
			position += MUST_SPACE.length();
			status = DFAStatus.NULL;
		} else if (startsWith(TAB)) {
			position += TAB.length();
			status = DFAStatus.NULL;
		} else {
			throw new SymbolError("语法错误:" + tagChar[position]);
		}
	}

	public String getAttr(String name) {
		return result.get(name);
	}

	public TagParser(String str) {
		this.tagChar = str.toCharArray();
	}

	@Override
	public String toString() {
		return result.toString();
	}

	public static class SymbolError extends Exception {
		private static final long serialVersionUID = 2441411373778495898L;

		public SymbolError(String msg) {
			super(msg);
		}
	}

	public static class Entity {
		public Entity(String name) {
			this.name = name;
		}

		public String name;
		public String value;

		@Override
		public String toString() {
			return "[" + name + ":" + value + "]";
		}
	}

	public enum DFAStatus {
		UNSTART, START, SYMBOL_START, SYMBOL_END, DONE, NULL, EQ
	}
}

时间: 2024-10-27 06:42:16

Java解析HTML标签Tag的相关文章

Java 解析 XML

Java 解析 XML XML解析技术有两种 DOM SAX DOM方式 根据XML的层级结构在内存中分配一个树形结构,把XML的标签,属性和文本等元素都封装成树的节点对象 优点: 便于实现增 删 改 查 缺点: XML文件过大可能造成内存溢出 SAX方式 采用事件驱动模型边读边解析:从上到下一行行解析,解析到某一元素, 调用相应解析方法 优点: 不会造成内存溢出, 缺点: 查询不方便,但不能实现 增 删 改 不同的公司和组织提供了针对DOM和SAX两种方式的解析器 SUN的jaxp Dom4j

Java解析XML文件的四种方法

[摘要] 可扩展标志语言(XML)在实现信息标准化.信息的交流与共享上有其独特的技术优势,因此受到了广泛的重视.本文先简单的介绍了XML基本知识,然后从XML应用入手总结了四种现今最常见的XML的解析方法,介绍了这四种方法的特点,其中包括优点与不足之处.最后给出了一个简单的案例来对这四种解析进行代码介绍. [关键字] XML文件,DOM,SAX,JDOM,DOM4J [引言] XML即可扩展标记语言(EXtensible Markup Language),是标准通用标记语言的子集,是一种用于标记

java解析xml文件四种方式介绍、性能比较和基本使用方法

一.介绍: 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的.DOM以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何时候在树中上下导航,而不

JAVA解析XML之SAX方式

JAVA解析XML之SAX方式 SAX解析xml步骤 通过SAXParseFactory的静态newInstance()方法获取SAXParserFactory实例factory 通过SAXParserFactory实例的newSAXParser()方法返回SAXParser实例parser 创建一个类继承DefaultHandle,重写方法进行业务处理并创建这个类的实例handle 重写DefaultHandle类的方法 startElement方法用来遍历xml文件的开始标签; endEle

JSP自定义分页标签TAG

首先我们需要在WEB-INF/tld/目录下创建page.tld文件 <?xml version="1.0" encoding="ISO-8859-1"?> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>page</short-name> <u

java超强分页标签演示

最近在做一个项目,用到了一个分页,于是动手写了个分页标签,先将代码贴出来,供大家交流,写的不好,请见谅!. 以下是java标签类,继承自SimpleTagSupport [java] view plaincopyprint? package com.lynn.oa.tag; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.jsp.JspExcep

详解Java解析XML的四种方法

(1)DOM解析 DOM是html和xml的应用程序接口(API),以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取 和操作文档的任意部分,是W3C的官方标准 [优点] ①允许应用程序对数据和结构做出更改. ②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据. [缺点] ①通常需要加载整个XML文档来构造层次结构,消耗资源大. [解析详解] ①构建Document对象: DocumentBuilderFactory dbf = DocumentBu

struts2 官方系列教程三:使用struts2 标签 tag

避免被爬,先贴上本帖地址:struts2 官方系列教程一:使用struts2 标签 tag http://www.cnblogs.com/linghaoxinpian/p/6901316.html 本教材假定你已完成了HelloWorld项目,你可以在 struts2 官方系列教程三:使用struts2 标签 tag 下载本章节的代码 在上一节教程中,我们在index.jsp中使用 url tag 创建了一个超链接hello.action 这节我们将探索struts2中其它tags Web应用程

Java学习——JSTL标签与EL表达式之间的微妙关系

原文总结的太好了,忍不住记录.转发. 原文地址:http://blog.csdn.net/u010168160/article/details/49182867 目录(?)[-] 一EL表达式 EL相关概念 EL基本格式 EL语法组成-标识符 PS使用EL的时候默认会以一定顺序pageContextrequestsessionapplication搜索四个作用域将最先找到的变量值显示出来 开启和关闭EL表达式 二JSTL标签库 相关概念 JSTL标签库分类 JSTL的优点 为什么要用JSTL 使