常见的XML解析技术:
1.DOM(基于XML树结构,比较耗资源,适用于多次访问XML);
2.SAX(基于事件,消耗资源小,适用于数量较大的XML);
3.JDOM(比DOM更快,JDOM仅使用具体类,而不是用接口);
4.DOM4J(非常优秀的Java,XML,API,性能优异,功能强大,开放源代码);
正则符号:
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。
* 字符串支持正则表达式的方法
* matches(String regex):将字符串与指定的正则表达式进行匹配,匹配成功返回true,否则返回false
*
* 电话号码的校验:3为区号+8位电话号码 4位区号+7位电话号码
* 010-12345678(01012345678) 021-12345678 027-12345678 029-12345678....
* 0371-1234567(03711234567)
* 网址校验:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?
* http://www.baidu.com
* http://www.baidu.com/index.html
public class TestVertify2 {
/**
* 校验电话号码
* @param tel
*/
public static boolean checkTel(String tel){
// String regex="\\d{3,4}-?\\d{7,8}";
String regex="((0[12]\\d{1})-?\\d{8})|(0\\d{3})-?\\d{7}";
return tel.matches(regex);
}
/**
* 校验网址:http://www.baidu.com
* @param url
* @return
*/
public static boolean checkURL(String url){
String regex="http://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?";
return url.matches(regex);
} /**
* 校验QQ号码
* @param qq
* @return
*/
public static boolean checkQQ(String qq){
String regex="[1-9]\\d{4,14}";
return qq.matches(regex); }
public static void main(String[] args) {
// boolean is = checkTel("021-12345678");
boolean is = checkURL("http://www.baidu.com/index.html");
System.out.println(is);
}
}
* 字符串中支持正则表达式的常用方法:
* ***matches(String regex):将字符串与指定的正则表达式进行匹配,匹配成功返回true,否则返回false
* **replaceAll(String regex, String replacement)
* 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
* replaceFirst(String regex, String replacement)
* 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
* split(String regex)
* 根据给定正则表达式的匹配拆分此字符串。
public class TestString {
public static void testReplace(){
String str="我是张三,我的QQ:12345,我的电话是:0371-1234567";
String regex="\\d+";
// str = str.replaceAll(regex, "#");
str = str.replaceFirst(regex, "#");
System.out.println(str);
} public static void testSplit(){
String str="java,html,,oracle,,,mysql,,,,javascript";
String regex=",+";//可以匹配一次或多次逗号
String[] strs = str.split(regex);
for (String string : strs) {
System.out.println(string);
}
}
public static void main(String[] args) {
testSplit();
}
}
*ava.util.regex 包主要包括以下二个类:
Pattern 类:
pattern 对象是一个正则表达式的编译表示。
Pattern 类没有公共构造方法。要创建一个 Pattern 对象,
你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
常用的方法:
compile(String regex) 将给定的正则表达式编译到模式中。
matches(String regex, CharSequence input) 编译给定正则表达式并尝试将给定输入与其匹配。
matcher(CharSequence input) 创建匹配给定输入与此模式的匹配器。
Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。
与Pattern 类一样,Matcher 也没有公共构造方法。
你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
常用方法:
find() 尝试查找与该模式匹配的输入序列的下一个子序列。
public class TestRegex {
public static void testPattern(){
String content="bjsxt java is good school!";
String regex = ".*java.*";
boolean isMatcher= Pattern.matches(regex, content);
System.out.println("是否包含'java'子字符串:"+isMatcher);
} public static void testMatches(){
String line = "This order was placed for QT3000! OK?";
String regex = "(\\D*)(\\d+)(.*)";
//1.创建Pattern对象
Pattern pattern = Pattern.compile(regex);
//2.创建Mather对象
Matcher matcher=pattern.matcher(line);
if(matcher.find()){
System.out.println("第一组:"+matcher.group()); //找全部
System.out.println("第二组:"+matcher.group()); // (\\D*)
System.out.println("第三组:"+matcher.group()); // (\\d+)
System.out.println("第四组:"+matcher.group()); // (.*)
}
} public static void main(String[] args) {
// testPattern();
testMatches();
}
}
eg:
*网络爬虫:将网易主页源码上的超级链接提取出来。
*1.获取网页主页的源码
*2.使用正则表达式进行匹配源码,将超级链接提取
public class WebSipder {
public static void main(String[] args) {
try {
//获取网易源码
URL url = new URL("http://www.163.com");
InputStream ips = url.openStream();
InputStreamReader isr = new InputStreamReader(ips);
BufferedReader br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String str;
while((str=br.readLine())!=null){
sb.append(str+"\n");
}
// System.out.println(sb);
//从源码中提取网址 http://yuedu.163.com
String regex="http://\\w*\\.*\\w*\\.com";
//创建一个pattern对象(正则表达式)
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sb);
while(matcher.find()){
String address = matcher.group();
System.out.println(address);
}
br.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} }
}
XML文档:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="">
<name>张三</name>
<course>java</course>
<score></score>
</student>
<student id="">
<name>李四</name>
<course>oracle</course>
<score></score>
</student>
</students>
DTD:文档类型定义
<?xml version="1.0" encoding="UTF-8"?>
<!--
DTD(文档类型定义):验证XML内容的合法性。
语法: <!DOCTYPE 根元素 [
<!ELEMENT 元素名称 (子元素名称,子元素名称,子元素名称) >
<!ELEMENT 子元素名称 (#PCDATA)>
<!ELEMENT 子元素名称 (#PCDATA)>
<!ELEMENT 子元素名称 (#PCDATA)>
]>
-->
<!DOCTYPE books [
<!ELEMENT books (book+)> //必须得有空格隔开才不报错
<!ELEMENT book (name,author,price)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]> <books>
<book>
<name>三国</name>
<author>罗贯中</author>
<price></price>
</book>
<book>
<name>水浒</name>
<author>施耐庵</author>
<price></price>
</book>
</books>
DOM:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student id="">
<name>张三</name> </student>
<student id="">
<name>李四</name> </student>
</students>
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; /**
*DOM(Document Object Model)文档对象模型
*DOM的特点:
*需要一次性将xml文件加载内存中,常驻内存,对内存资源占用较大,适合多次访问的XML解析
*DOM解析的步骤
*1.创建一个解析器工厂对象
*2.创建一个解析器
*3.使用解析器对xml文件进行解析,将xml文档构成一个Document并返回
*4.以Document为基础,遍历其中的内容以获取和操作响应的节点和数据
*/
public class TestDomParse {
public static void main(String[] args) {
//1.创建工厂解析器
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//2.创建解析对象
DocumentBuilder db = dbf.newDocumentBuilder();
//3.将xml文档转换为Document对象
Document document = db.parse(new FileInputStream("scores.xml"));
//4.以document对象为基础,获取子元素
// Element root = document.getDocumentElement();//根节点students
//根据标签名称获取该标签的列表
NodeList nodeList = document.getElementsByTagName("students");
Node rootNode=nodeList.item();//根节点
NodeList studentNodeList = rootNode.getChildNodes();//获取父节点的子节点(student节点的集合)
//遍历子节点
for (int i = ; i < studentNodeList.getLength(); i++) {
Node studentNode = studentNodeList.item(i);//获取子节点
if(studentNode.getNodeType()==Node.ELEMENT_NODE){
Element studentElement = (Element)studentNode;//student节点
String id = studentElement.getAttribute("id");
System.out.println("id="+id);
NodeList subNodeList = studentElement.getChildNodes();//获取student节点的子节点列表
//遍历student的子节点列表
for (int j = ; j < subNodeList.getLength(); j++) {
Node subNode = subNodeList.item(j);//name,course,score
if(subNode.getNodeType()==Node.ELEMENT_NODE){
String text = subNode.getTextContent();//获取文本节点
System.out.println(subNode.getNodeName()+"="+text);
}
}
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} }
}
DOM4J:
import java.io.File;
import java.util.Iterator; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; /**
* DOM4J:开源项目(针对XML进行解析和操作的开源API)
* 使用DOMJ解析XML步骤:
* 1.添加dom4j的类库:先将dom4_xx.jar复制到项目中,选择dom4j_xx.jar右键:build path--->add to build path
* 2.指定要解析的XML文件
* 3.将XML文件转换为Document对象(文档树)
* SAXReader saxReader = new SAXReader();
* Doucment document = saxReader.read(file);
* 4.遍历Document中的元素,获取其属性,文本节点中内容。
*
* Document中的常用方法
* getRootElement():获取文档中的根节点
* Element中的常用方法
* elementIterator():获取该元素的所有子元素
* attributeValue(String attrName):根据属性名称获取该属性的值
* getName():获取该元素的元素名称
* getText():获取该元素的文本节点
*/
public class TestDom4jParse {
public static void main(String[] args) {
//2.指定要解析XML文件
File file = new File("scores.xml");
//3.将XML文件转换为Document文档
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(file);
//获取根节点:getRootElement()
Element root = document.getRootElement();//students节点
//获取根节点的子节点
Iterator<Element> studentIter = root.elementIterator();
while(studentIter.hasNext()){
Element student = studentIter.next();//获取student节点
String id = student.attributeValue("id");//获取id属性的值
System.out.println("id="+id);
//获取学生节点的子节点
Iterator<Element> subIter= student.elementIterator();
while(subIter.hasNext()){
Element subElement= subIter.next();
String name = subElement.getName();//获取元素的名称
String text = subElement.getText();
System.out.println(name+"--->"+text);
}
}
} catch (DocumentException e) {
e.printStackTrace();
} }
}
DOM4J创建XML文档:
import java.io.FileWriter;
import java.io.IOException; import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter; /**
* <products>
* <product id="001">
* <name>iphone8</name>
* <price>1500</price>
* </product>
* <product id="002">
* <name>iphone8 plus</name>
* <price>1600</price>
* </product>
* </products>
* 通过dom4j生成一个xml文件 * 1.创建Document对象(空的文档数)
2.向Document对象中添加子节点和属性
3.通过XMLWriter和IO流将document写入文件中
*/
public class TestDom4jWriter {
public static void main(String[] args) {
// 构建一个Document对象
Document document = DocumentHelper.createDocument();
// 为document对象添加根节点
Element products = document.addElement("products");
// 为products节点添加子节点
Element product = products.addElement("product");
product.addAttribute("id", "");// 为product添加属性
Element name = product.addElement("name");
name.setText("iphone8");// 设置name的文本节点
Element price = product.addElement("price");
price.setText("");
// 为products节点添加子节点
Element product2 = products.addElement("product");
product2.addAttribute("id", "");// 为product添加属性
Element name2 = product2.addElement("name");
name2.setText("iphone8 plus");// 设置name的文本节点
Element price2 = product2.addElement("price");
price2.setText(""); try {
//将document对象写入文件中
FileWriter fw = new FileWriter("test.xml");
OutputFormat ops = OutputFormat.createPrettyPrint();
ops.setEncoding("GBK");
ops.setIndent(true);//设置缩进
XMLWriter xmlWriter = new XMLWriter(fw,ops);
xmlWriter.write(document);//将document写入到文件中
xmlWriter.flush();
xmlWriter.close();
System.out.println("写入完成!");
} catch (IOException e) {
e.printStackTrace();
} }
}
DOM4J将所解析XML的文档封装在类中:
package cn.zzsxt.homework;
/**
* 用于封装xml解析出的servlet节点中的信息
*<servlet>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet>
* @author Administrator:实体类(封装数据)
*
*/
public class ServletBean {
private String servletName;//封装servlet-name中节点中的值
private String urlPattern;//封装url-pattern节点中的值
public ServletBean(){ } public ServletBean(String servletName,String urlPattern){
this.servletName=servletName;
this.urlPattern=urlPattern;
} public String getServletName() {
return servletName;
} public void setServletName(String servletName) {
this.servletName = servletName;
} public String getUrlPattern() {
return urlPattern;
} public void setUrlPattern(String urlPattern) {
this.urlPattern = urlPattern;
} }
package cn.zzsxt.homework; import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter; public class Homework {
/**
* 生成xml的方法
*/
public static void writer(){
//1.创建一个Document对象(空文档树)
Document document = DocumentHelper.createDocument();
//2.为文档添加节点
Element webapps = document.addElement("webapps");
//3.为webapps节点添加子节点
Element servlet1 = webapps.addElement("servlet");
Element servlet2 = webapps.addElement("servlet");
//4.为servlet节点添加子节点
Element servletName1= servlet1.addElement("servlet-name");
Element urlPattern1= servlet1.addElement("url-pattern");
//5.为servlet节点添加文本
servletName1.setText("LoginServlet");
urlPattern1.setText("/LoginServlet");
Element servletName2= servlet2.addElement("servlet-name");
Element urlPattern2= servlet2.addElement("url-pattern");
servletName2.setText("IndexServlet");
urlPattern2.setText("/IndexServlet");
//6.将Document写入文件
try {
FileWriter fw = new FileWriter(new File("web.xml"));
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");//设置编码集
format.setIndent(true);//设置缩进
XMLWriter xmlWriter = new XMLWriter(fw, format);
xmlWriter.write(document);
xmlWriter.close();
System.out.println("web.xml已经生成!");
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 解析web.xml,将servlet子节点中的信息封装到ServletBean对象中,并将其加入到List中进行返回。
* @return
*/
public static List<ServletBean> parseXML(){
List<ServletBean> list = new ArrayList<ServletBean>();
//解析XML文件
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(new File("web.xml"));
//获取根节点
Element webapps = document.getRootElement();
Iterator<Element> servletIter= webapps.elementIterator();
while(servletIter.hasNext()){
Element servlet = servletIter.next();//servlet节点
Iterator<Element> servletSubIter = servlet.elementIterator();
//创建一个ServletBean对象,用于封装servlet子节点中的信息
ServletBean servletBean = new ServletBean();
while(servletSubIter.hasNext()){
Element subElement= servletSubIter.next();//servlet-name和url-pattern
String elementName = subElement.getName();
//将servlet-name节点中文本封装到ServletBean的servletName属性中
if(elementName.equals("servlet-name")){
String servletName = subElement.getText();
servletBean.setServletName(servletName);
}else if(elementName.equals("url-pattern")){
//将url-pattern节点中文本封装到ServletBean的urlPattern属性中
String urlPattern =subElement.getText();
servletBean.setUrlPattern(urlPattern);
}
}
//将ServletBean添加到List集合中
list.add(servletBean);
}
} catch (DocumentException e) {
e.printStackTrace();
}
return list;
}
public static void main(String[] args) {
// writer();
List<ServletBean> list = parseXML();
for (ServletBean servletBean : list) {
System.out.println(servletBean.getServletName()+"----"+servletBean.getUrlPattern());
}
}
}