转自http://www.mamicode.com/info-detail-1197564.html
1 DOM4J简介
DOM4J是dom4j.org出品的一个开源XML解析包。Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。
它的主要接口都在org.dom4j这个包里定义:
接口类 | 说明 |
---|---|
Attribute | Attribute定义了XML的属性 |
Branch | Branch为能够包含子节点的节点如XML元素(Element)和文档(Document)定义了一个公共的行为。 |
CDATA | CDATA定义了XML CDATA区域,XML 文档中的文本通常解析为字符数据,或者(按照文档类型定义术语)称为 PCDATA。XML 的特殊字符(&、< 和 >)在 PCDATA 中可以识别,并用于解析元素名称和实体。CDATA(字符数据)区域被解析器视为数据块,从而允许您在数据流中包含任意字符。CDATA 区域的起始标记是一个特殊的序列 序列。这些标记之间的任何内容都将原封不动地通过 XML 解析器。 |
CharacterData | CharacterData是一个标识接口,标识基本字符的节点。如CDATA,Comment,Test。 |
Comment | Comment定义了XML注释的行为 |
Doucument | 定义了XML文档 |
DocumentType | DocumentType定义XML DOCTYPE声明 |
Element | Element定义了XML元素,即一个XML标签及其内容 |
ElementHandler | DlementHandler定义了Element对象的处理器 |
ElementPath | 被ElementHandler使用,用于取得当前正在处理的路径层次信息 |
Entity | Entity定义XML entity |
Node | Node为所有的dom4j中xml节点定义了多态行为,它是dom4j树中所有节点的根接口 |
NodeFilter | NodeFilter定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate) |
ProcessingInstruction | ProcessingInstruction定义XML处理指令 |
Text | Text定义XML文本节点 |
Visitor | Vistor用于实现Visitor模式 |
XPath | XPath在分析一个字符串后会提供一个XPath表达式 |
2 dom4j常用操作
2.1 获取类加载目录下的xml文件生成Document对象
//获取类加载文件目录,substring(6)为了去掉path中的file:/前缀
String resourcePath = Class.class.getResource("/").toString().substring(6);
//读取该路径下的xxx.xml文件生成Document对象
SAXReader reader = new SAXReader();
//read方法可以从InputStream、File、Url等多种不同的源来读取
Document doc = reader.read(new File(resourcePath+"xxx.xml"));
//打印document内容
System.out.println(doc.asXML());
2.2 读取Root节点
一切XML分析都是从Root元素开始的
doc.getRootElement();
2.3 遍历XML树
DOM4J提供了至少3种遍历节点的方法:
2.3.1 枚举(Iterator)
//枚举所有子节点
for(Iterator i=root.elementIterator();i.hasNext();){
Element e=(Element)i.next();
}
//枚举名称为foo的节点
for(Iterator i=root.elementIterator(foo);i.hasNext()){
Element e=(Element)i.next();
}
//枚举属性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
Attribute attribute = (Attribute) i.next();
}
2.3.2 递归
public void treeWalk(){
treeWalk(doc.getRootElement());
}
public void treeWalk(Element e){
for(int i = 0, size = e.nodeCount(); i < size; i++){
Node node = e.node(i);
if(node instanceof Element){
treeWalk((Element)node);
}else{
//do something...
}
}
}
2.3.3 Visitor模式
DOM4J提供对Visitor的支持,这样可以大大缩减代码量,并且清楚易懂。了解设计模式的人都知道,Visitor是GOF设计模式之一。其主要原理就是两种类互相保有对方的引用,并且一种作为Visitor去访问许多Visitable。
//自定义一个类实现Visitor接口
public class MyVisitor extends org.dom4j.VisitorSupport{
public void visit(Element e){
System.out.println(e.getName());
}
public void visit(Attribute attr){
System.out.println(attr.getName());
}
}
//调用:root.accept(new MyVisitor());
visitor接口提供多种Visit()的重载,根据XML不同的对象,将采用不同的方式来访问。上面是给出的Element和Attribute的简单实现,一般比较常用的就是这两个。VisitorSupport是DOM4J提供的默认适配器,Visitor接口的Default Adapter模式,这个模式给出了各种visit(*)的空实现,以便简化代码。
注意,这个Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历指定子节点。我第一次用的时候,认为是需要自己遍历,便在递归中调用Visitor,结果可想而知。
2.3.4 XPath支持
DOM4J对XPath有良好的支持,如访问一个节点,可以直接用XPath选择。使用XPath需要添加jaxen的jar包
public void bar(Document document) {
List list = document.selectNodes( "//foo/bar" );
Node node = document.selectSingleNode("//foo/bar/author");
String name = node.valueOf( "@name" );
}
如果想查找XHTML文档中所有的超链接,下面的代码可以实现:
public void findLinks(Document doc) throws DocumentException{
List list=doc.selectNodes("//a/@href");
for(Iterator iter=list.iterator;iter.next();){
Attribute attr=(Attribute)iter.next();
String url=attr.getValue();
}
}
2.4 类型转换
2.4.1 字符串与XML转换
//XML转换为字符串
Document doc = getDocument(file);
String text = doc.asXML();
//字符串转换为XML
String text="<person> <name>James</name> </person>";
Document document = DocumentHelper.parseText(text);
2.4.2 用XSLT转换XML
public Document styleDocument(Document doc,String stylesheet) throws Exception{
//load the transformer using JAXP
TransformerFactory factory=TransformerFactory.newInstance();
Transformer transformer=factory.newTransformer(new StreamSource(stylesheet));
}
//now lets style the given document
DocumentSource source=new DocumentSource(document);
DocumentResult result=new DocumentResult();
transformer.transform(source,result);
//return the transformed document
Document transformedDoc=result.getDocument();
return transformedDoc;
2.5 通过指定属性获得Element
//通过属性ID获取根元素下一级元素
public static Element getBigTypeElementById(Document doc,String id){
Element root = doc.getRootElement();
List<Element> elements = new ArrayList();
elements = root.elements();
for(Element e:elements){
if(id.equals(e.attributeValue("id"))){
return e;
}
}
return null;
}
2.6 创建XML
一般创建XML是写文件前的工作,这就像StringBuffer一样容易。
public Document createDocument(){
Document doc=DocumentHelper.createDocument();
Element root=doc.addElement("root");
Element author1=root.addElement("author").addAttribute("name","James").addAttribute("location","UK").addText("James Strachan");
Element author2=root.addElement("author").addAttribute("name","Bob").addAttribute("location","US").addText("Bob McWhirter");
}
return doc;
2.7 文件输出
一个简单的输出方法是将一个Document或任何的Node通过write方法输出
FileWriter out = new FileWriter( "foo.xml" );
document.write(out);
如果你想改变输出的格式,比如美化输出或缩减格式,可以用XMLWriter类
public void write(Document doc) throws IOException{
//指定文件
XMLWriter writer=new XMLWriter(new FileWriter(output.xml));
writer.writer(doc);
writer.close();
//美化格式
OutputFormat format=OutputFormat.creatPrettyPrint();
//指定输出的字符编码格式
format.setEncoding("UTF-8");
writer=new XMLWriter(System.out,format);
writer.writer(doc);
//缩减格式
format=OutputFormat.createCompactFormat();
writer=new XMLWriter(System.out,format);
writer.writer(doc);
}
添加于2016.06.12:
使用format.setEncoding(“UTF-8”);指定编码格式后,发现写入硬盘的文件还是乱码。解决方法如下:
//修改前代码 OutputFormat format=OutputFormat.creatPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer=new XMLWriter(new FileWriter(new File(filePath)),format); writer.write(doc); //修改后代码 OutputFormat format=OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); //用FileOutputStream字节流代替FileWriter字符流即可 FileOutputStream fos = new FileOutputStream(new File(filePath)); XMLWriter writer=new XMLWriter(fos,format); writer.write(doc);
3 java web前后端交互
3.1 java返回xml类型的数据给javascript
java文件中:
HttpServletResponse resp = ServletActionContext.getResponse();
resp.setContentType("text/xml; charset=UTF-8");
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
resp.setDateHeader("Expires", 0);
try {
out=resp.getWriter();
Document document = XMLUtil.getDocument(xmlFilePath);
out.write(document.asXML());
out.flush();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(out!=null){
out.close();
}
}
javascript文件:
$.ajax(
url:"xxx",
dataType:'xml',
type:'POST',
success:function(xml){
$(xml).find("tagName").each(function(i,n){
xxx;
});
}
);