1、XML解析(dom4j)

1.1 读取XML文档

// 从文件读取XML,输入文件名,返回XML文档
public Document read(String fileName) throws MalformedURLException, DocumentException {SAXReader reader = new SAXReader();Document document = reader.read(new File(fileName));return document;
}

1.2 获取ROOT节点

public Element getRootElement(Document doc){return doc.getRootElement();
}

1.3 遍历XML树

1.3.1 列举3中遍历方法:
1.3.1.1 枚举(Iterator)
// 枚举所有子节点
for ( Iterator i = root.elementIterator(); i.hasNext(); ) {Element element = (Element) i.next();// 业务逻辑
}
// 枚举名称为foo的节点
for ( Iterator i = root.elementIterator(foo); i.hasNext();) {Element foo = (Element) i.next();// 业务逻辑
}
// 枚举属性
for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {Attribute attribute = (Attribute) i.next();// 业务逻辑
}
1.3.1.2 递归
public void treeWalk() {Document document = read("XML文件路径");treeWalk(getRootElement(document));
}
public void treeWalk(Element element) {for (int i = 0, size = element.nodeCount(); i < size; i++)     {Node node = element.node(i);if (node instanceof Element) {treeWalk((Element) node);} else { // 业务逻辑}}
}
1.3.1.3 Visitor模式
Visitor是自动遍历所有子节点的。如果是root.accept(MyVisitor),将遍历子节点
1、定义一个类继承VisitorSupport(实现了Visitor接口)public class MyVisitor extends VisitorSupport {public MyVisitor() {}@Overridepublic void visit(Document document) {System.out.println("visit-document = [" + document.asXML() + "]");}@Overridepublic void visit(DocumentType documentType) {super.visit(documentType);}@Overridepublic void visit(Element node) {// isTextOnly() : 可以对一个Element对象调用isTextOnly()方法判断它是否含有textif (node.isTextOnly()) {// 含有textSystem.out.println(node.getName() +" "+":"+" "+ node.getText());} else {// 存在子节点System.out.println("node = [" + node.getName() + "]");}}@Overridepublic void visit(Attribute node) {super.visit(node);}@Overridepublic void visit(CDATA node) {super.visit(node);}@Overridepublic void visit(Comment node) {super.visit(node);}@Overridepublic void visit(Entity node) {super.visit(node);}@Overridepublic void visit(Namespace namespace) {super.visit(namespace);}@Overridepublic void visit(ProcessingInstruction node) {super.visit(node);}@Overridepublic void visit(Text node) {super.visit(node);}
}2、调用visit方法
public static void main(String[] args) throws DocumentException {MyVisitor myVisitor = new MyVisitor();String resSucc = "<result><MSG><MSG><array><AAC>*****</AAC><AAE>****</AAE><AAA>*</AAA><AAC>*</AAC><AAC>***</AAC><AAC>********</AAC><AAC>******</AAC></array></MSG><SUCCESS>****</SUCCESS></MSG><SUCCESS>****</SUCCESS></result>";// String转XMLDocument document = DocumentHelper.parseText(resSucc);// 自动遍历子节点document.accept(myVisitor);System.out.println("=================================");Element rootElement = document.getRootElement();// 自动遍历子节点rootElement.accept(myVisitor);}3、执行结果:
visit-document = [<?xml version="1.0" encoding="UTF-8"?>
<result><MSG><MSG><array><AAC>*****</AAC><AAE>****</AAE><AAA>*</AAA><AAC>*</AAC><AAC>***</AAC><AAC>********</AAC><AAC>******</AAC></array></MSG><SUCCESS>****</SUCCESS></MSG><SUCCESS>****</SUCCESS></result>]
node = [result]
node = [MSG]
node = [MSG]
node = [array]
AAC : *****
AAE : ****
AAA : *
AAC : *
AAC : ***
AAC : ********
AAC : ******
SUCCESS : ****
SUCCESS : ****
=================================
node = [result]
node = [MSG]
node = [MSG]
node = [array]
AAC : *****
AAE : ****
AAA : *
AAC : *
AAC : ***
AAC : ********
AAC : ******
SUCCESS : ****
SUCCESS : ****之所以会打印两遍子节点的信息,是因为document.accept(myVisitor)中调用了Element的accpt()方法,即rootElement.accept(myVisitor)/** *还可以使用内部类的方式调用Visitor,由于自定义的Visitor是需要继承VisitorSupport类,而VisitorSupport  是实现的Visitor接口,所以这里直接用内部类的形式调用visit()方法:*/String text = "<skills>\n" +"<!--第一个技能-->\n" +"<skill name=\"独孤九剑\">\n" +"<info>为独孤求败所创,变化万千,凌厉无比。其传人主要有风清扬、令狐冲。</info>\n" +"</skill>\n" +"<skill name=\"葵花宝典\">\n" +"<info>宦官所创,博大精深,而且凶险至极。练宝典功夫时,首先要自宫净身。</info>\n" +"</skill>\n" +"<skill name=\"北冥神功\">\n" +"<info>逍遥派的顶级内功之一,能吸人内力转化为自己所有,威力无穷。</info>\n" +"</skill>\n" +"</skills>";
Document document1 = DocumentHelper.parseText(text);
Element rootElement1 = document1.getRootElement();
Element skill = rootElement1.element("skill");
skill.accept(new Visitor() {@Overridepublic void visit(Document document) {}@Overridepublic void visit(DocumentType documentType) {}@Overridepublic void visit(Element element) {System.out.println("element = [" + element.asXML() + "]");}@Overridepublic void visit(Attribute attribute) {}@Overridepublic void visit(CDATA cdata) {}@Overridepublic void visit(Comment comment) {}@Overridepublic void visit(Entity entity) {}@Overridepublic void visit(Namespace namespace) {}@Overridepublic void visit(ProcessingInstruction processingInstruction) {}@Overridepublic void visit(Text text) {}
});// 打印内容:
// element = [<skill name="独孤九剑">
// <info>为独孤求败所创,变化万千,凌厉无比。其传人主要有风清扬、令狐冲。</info>
// </skill>]
// element = [<info>为独孤求败所创,变化万千,凌厉无比。其传人主要有风清扬、令狐冲。</info>]

1.4 XPath支持

selectNodes语法:String resSucc = "<result><MSG><MSG name=\"测试\"><array><AAC>*****</AAC><AAE>****</AAE><AAA>*</AAA><AAC>*</AAC><AAC>***</AAC><AAC>********</AAC><AAC>******</AAC></array></MSG><SUCCESS>****</SUCCESS></MSG><SUCCESS>****</SUCCESS></result>";// String转XML
Document document = DocumentHelper.parseText(resSucc);
// 获取根节点
Element rootElement = document.getRootElement();// 1、selectNodes("MSG") :从当前节点的子节点中选择名称为 result 的节点。
List<Node> nodes = rootElement.selectNodes("MSG");
nodes.forEach((node -> {System.out.println("node = [" + node.getName() + "]");
}));// 2、selectNodes("/MSG") :从根节点的子节点中选择名称为 result 的节点。
nodes = rootElement.selectNodes("/MSG");
nodes.forEach((node -> {System.out.println("/node = [" + node.getName() + "]");
}));// 3、selectNodes("//MSG") :从任意位置的节点上选择名称为 result 的节点
nodes = rootElement.selectNodes("//MSG");
nodes.forEach((node -> {System.out.println("//node = [" + node.getName() + "]");
}));// 4、selectNodes(".") :选择当前节点。
nodes = rootElement.selectNodes(".");
nodes.forEach((node -> {System.out.println(".node = [" + node.getName() + "]");
}));// 5、selectNodes("..") :选择当前节点的父节点。
nodes = rootElement.selectNodes("..");
nodes.forEach((node -> {System.out.println("..node = [" + node.getName() + "]");
}));// 6、selectNodes("//MSG[@name]") :在 selectNodes("//MSG") 的基础上,增加了一个限制,就是要求拥有 name 属性。
nodes = rootElement.selectNodes("//MSG[@name]");
nodes.forEach((node -> {System.out.println("[@name]node = [" + node.getName() + "]");
}));// 7、selectNodes("//MSG[@name='测试']") :在 selectNodes("//MSG") 的基础上,electNodes("//item[@name]") 的基础上,增加了一个限制,就是要求 name 属性值为 测试。注意语法中有引号;如果没有引号,则表示是数字类型,对于数字类型可以使用大于号、小于号等。
nodes = rootElement.selectNodes("//MSG[@name='测试']");
nodes.forEach((node -> {System.out.println("[@name='测试']node = [" + node.getName() + "]");
}));// 8、selectSingleNodes("MSG") :只拿第一个MSG节点。
nodes = rootElement.selectSingleNodes("MSG");
nodes.forEach((node -> {System.out.println("node = [" + node.getName() + "]");
}));

1.5 字符串与XML相互转换

// XML转字符串
Document document = ...;
String text = document.asXML();// 字符串转XML
String text = James ;
Document document = DocumentHelper.parseText(text);

1.6 创建XML

public static void main(String[] args) {// 创建文档Document document = DocumentHelper.createDocument();// 创建根节点Element root = document.addElement("root");root// 当前节点下添加子节点.addElement("author")// 添加属性.addAttribute("name", "James").addAttribute("location", "UK")// 添加文本内容.addText("James Strachan");root.addElement("author").addAttribute("name", "Bob").addAttribute("location", "US").addText("Bob McWhirter");System.out.println("root:\n" + root.asXML() + "]");}执行结果:
<root><author name="James" location="UK">James Strachan</author><author name="Bob" location="US">Bob McWhirter</author></root>

1.7 文件输出

此处代码接上一节代码:System.out.println("文件输出准备······");
/*** FileOutputStream:字节流,通常用于读写原始字节数据,如图像;可以将文件转成字节数组;读取单位为一个子节*/
try {OutputFormat format = OutputFormat.createPrettyPrint();format.setEncoding("UTF-8");XMLWriter xmlWriter = new XMLWriter(new  FileOutputStream("C:\\Users\\Administrator\\Desktop\\CreateXml" +".xml"), format);// 如果输出整个xml文档,则会带上xml头<?xml version="1.0" encoding="UTF-8"?>//            xmlWriter.write(rootDocument);// 如果只输出根节点部分,则不会带xml头xmlWriter.write(root);xmlWriter.close();
} catch (Exception e) {System.out.println("文件输出失败:" + e.getMessage());throw e;
}
System.out.println("文件输出完成\n");/*** FileWriter:字符流,通常用于读写文本数据;读取单位为一个字符,可能是一个字节,也可能是两个字节*/
try {OutputFormat format = OutputFormat.createPrettyPrint();format.setEncoding("UTF-8");XMLWriter xmlWriter = new XMLWriter(new FileWriter(new  File("C:\\Users\\Administrator\\Desktop\\CreateXml2.xml")), format);// 如果输出整个xml文档,则会带上xml头<?xml version="1.0" encoding="UTF-8"?>//            xmlWriter.write(rootDocument);// 如果只输出根节点部分,则不会带xml头xmlWriter.write(root);xmlWriter.close();
} catch (Exception e) {System.out.println("文件输出失败:" + e.getMessage());throw e;
}System.out.println("输出控制台开始");
try {OutputFormat format = OutputFormat.createPrettyPrint();format.setEncoding("UTF-8");XMLWriter writer = new XMLWriter(System.out, format);writer.write(root);writer.flush();
} catch (Exception e) {System.out.println("文件输出失败:" + e.getMessage());throw e;
}
System.out.println("\n输出控制台完成");

1.8 xml节点解析方法

1.8.1 selectNodes() 和 selectSingleNode()
此处代码接1.6节代码:root.selectNodes("author").forEach((ele) -> {// 查找根节点下的所有author节点并打印节点名称System.out.println("eleName = [" + ele.getName() + "]");
});
// 打印内容:
// name = [author] - value = [James Strachan]
// name = [author] - value = [Bob McWhirter]Node author = root.selectSingleNode("author");
// 获取第一个author节点中的内容
System.out.println("node = [" + author.getText() + "]");
// 打印内容:
// node-value = [James Strachan]// 获取当前节点的路径
System.out.println("node-path = [" + author.getPath() + "]");
// 打印内容:
// node-path = [/root/author]
1.8.2 element() 和 elements()
/*** element() : 获取当前节点下的节点* elements() :获取当前节点下的子节点,装载到list并返回,可在此方法上调用size获取节点数*/此示例接1.6节代码:
// 获取跟节点下的节点并打印:
root.elements().forEach((ele) -> {System.out.println("eleName = [" + ele.getName() + "]");
});
// 打印内容:
// eleName = [author]
// eleName = [author]// 获取根节点下的所有author节点并打印:
root.elements("author").forEach((ele) -> {System.out.println("elements = [" + ele.getName() + "]");
});
// elements = [author]
// elements = [author]String result = "<result><MSG><MSG><array><AAC>**</AAC><AAE>*****</AAE></array></MSG></MSG></result>";
Document doc = DocumentHelper.parseText(result);
Element rootElement = doc.getRootElement();
// 获取根节点下的MSG节点,继续获取MSG节点下的MSG节点并返回里面的节点数量
int count = rootElement.element("MSG").element("MSG").elements().size();
1.8.3 setName()
// 修改节点名称:
rootElement.element("MSG").element("MSG").setName("ERRMSG");
1.8.4 getText() 和 getStringValue()
String resSucc = "<result><MSG><MSG name=\"测试\"><array><AAC>*****</AAC><AAE>****</AAE><AAA>*</AAA><AAC>*</AAC><AAC>***</AAC><AAC>********</AAC><AAC>******</AAC></array></MSG><SU>****</SU></MSG><SU>****</SU></result>";// String转XML
Document document = DocumentHelper.parseText(resSucc);
// 获取当前节点下所有文本内容
System.out.println("StringValue = [" + document.getStringValue() + "]");
// 如果当前节点下是文本则返回文本,如果当前节点下还是节点则返回空值
System.out.println("Text = [" + document.getText() + "]");// 打印内容:
// StringValue = [************************************]
// Text = []
1.8.5 isTextOnly()
// 判断Element对象是否含有text文本数据
@Override
public void visit(Element node) {// isTextOnly() : 可以对一个Element对象调用isTextOnly()方法判断它是否含有textif (node.isTextOnly()) {// 含有textSystem.out.println(node.getName() +" "+":"+" "+ node.getText());} else {// 存在子节点System.out.println("node = [" + node.getName() + "]");}
}
1.8.6 自定义递归方法遍历所有节点内容
String resSucc = "<result><MSG><MSG name=\"测试\"><array><AAC>*****</AAC><AAE>****</AAE><AAA>*</AAA><AAC>*</AAC><AAC>***</AAC><AAC>********</AAC><AAC>******</AAC></array></MSG><SU>****</SU></MSG><SU>****</SU></result>";// String转XML
Document document = DocumentHelper.parseText(resSucc);
// 获取根节点
Element rootElement = document.getRootElement();
parse(rootElement);public static void parse(Element root) {List el = root.elements();//获得当前节点的所有子节点//遍历每个子节点for (Object o : el) {Element element = (Element) o;//如果该节点含有文本数据,也就是叶节点if (element.isTextOnly()) {List attList = element.attributes();//获得所有属性for (Object e : attList) {System.out.println(element.getQName().getName() + "元素的" + ((Attribute) e).getQName().getName() +"属性值为:" + ((Attribute) e).getValue());}//输出子节点的文本数据System.out.println(element.getTextTrim());} else {parse(element);}}
}
1.8.7 elementIterator()
/*** 对Document对象调用getRootElement()方法可以返回代表根节点的Element对象。拥有了一个Element对象后,可以对该对象调用elementIterator()方法获得它的子节点的Element对象们的一个迭代器。使用(Element)iterator.next()方法遍历一个iterator并把每个取出的元素转化为Element类型。*/
public static Document load(String filename) {  Document document = null;  try {  SAXReader saxReader = new SAXReader();  document = saxReader.read(new File(filename)); // 读取XML文件,获得document对象  } catch (Exception ex) {  ex.printStackTrace();  }  return document;
} public boolean isOnly(String catNameEn, HttpServletRequest request,  String xml) {  boolean flag = true;  String path = request.getRealPath("");  Document doc = load(path + "/" + xml);  Element root = doc.getRootElement();  for (Iterator i = root.elementIterator(); i.hasNext();) {  Element el = (Element) i.next();  if (catNameEn.equals(el.elementTextTrim("engName"))) {  flag = false;  break;  }  }  return flag;
}
1.8.8 Qname()
Qname:
1.来历:qname是qualified name 的简写
2.构成:由名字空间(namespace)前缀(prefix)以及冒号(:),还有一个元素名称构成
3.举例:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"version="1.0"><xsl:template match="foo"><hr/></xsl:template>
</xsl:stylesheet>
xsl是名字空间前缀,template是元素名称,xsl:template 就是一个qname
4.总结:qname无非是有着特定格式的xml元素,其作用主要是增加了名字空间,比如有同样的元素名称,而名字空间不同的情况。public static void main(String[] args) throws DocumentException {String text = "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n" +"xmlns=\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"\n" +"version=\"1.0\">\n" +"<xsl:template match=\"foo\">\n" +"<hr/>\n" +"</xsl:template>\n" +"</xsl:stylesheet>";Document document = DocumentHelper.parseText(text);Element rootElement = document.getRootElement();System.out.println("args = [" + rootElement.getQName().getNamespacePrefix() + "]");System.out.println("args = [" + rootElement.getQName().getQualifiedName() + "]");System.out.println("args = [" + rootElement.getQName("xsl:stylesheet").getName() + "]");System.out.println("args = [" + rootElement.getQName().toString() + "]");System.out.println("args = [" + rootElement.getQName().getNamespace() + "]");
}// 打印内容:
// NamespacePrefix = [xsl]
// QualifiedName = [xsl:stylesheet]
// QName = [stylesheet]
// args = [org.dom4j.QName@e42e6155 [name: stylesheet namespace: "org.dom4j.Namespace@ed4197ca [Namespace: prefix xsl mapped to URI "http://www.w3.org/1999/XSL/Transform"]"]]
// Namespace = [org.dom4j.Namespace@ed4197ca [Namespace: prefix xsl mapped to URI "http://www.w3.org/1999/XSL/Transform"]]

Java 使用dom4j进行XML解析相关推荐

  1. Java中四种XML解析技术之不完全测试

    Java中四种XML解析技术之不完全测试 <script language=javascript src=""></script> 在平时工作中,难免会遇到 ...

  2. 使用Dom4j进行XML解析

    2019独角兽企业重金招聘Python工程师标准>>> 1概述 在进行ESB集成项目中,使用到了很多系统的接口,这些接口传输的数据大部分都采用了XML的格式,这样在使用ESB开发服务 ...

  3. Java实现——Dom4j读写XML文件

    1. dom4j概述 解析DOM4J是一个开源XML解析包,采用了Java集合框架并完全支持DOM,SAX和JAXP.最大的特色是使用了大量的接口,主要接口都在org.dom4j里定义. 2. dom ...

  4. java自带的xml解析_Java自带的XML解析

    JAXP(Java API for XML Processing,意为处理XML的Java API) 解析XML一般有两种方式: 一种是DOM方式:一次性读取XML内容存入内存 优点:能进行各种增删改 ...

  5. java项目——Dom4j读取XML文件保存orecal数据库

    上一篇介绍了如何利用dom4j读取xml文件,连接数据库,换数据库的话直接修改XML文件,使配置更加灵 活,本篇博客主要介绍一下如何将XML文件导入到orecal数据库中. XML在现在的项目中的应用 ...

  6. 制衣厂普工小伙用java代码写的xml解析框架

    xml解析框架,这个框架也可以解析html,是我自己写的xml解析技术,花费我很多的时间,我在工厂做这个工作来维持生计↓↓↓↓↓↓↓↓ 哈哈哈,开个玩笑,下面这张图片才是我,这张图片是主管拍的 平均月 ...

  7. Java的4种XML解析

    在平时工作中,难免会遇到把 XML 作为数据存储格式.面对目前种类繁多的解决方案,哪个最适合我们呢?在这篇文章中,我对这四种主流方案做一个不完全评测,仅仅针对遍历 XML 这块来测试,因为遍历 XML ...

  8. java项目——Dom4j读取XML文件连接orecal数据库

    Dom4j介绍:           dom4j是一个简单的开源库,用于处理XML. XPath和XSLT,它基于Java平台,使用Java的集合框架,全面集 成了DOM,SAX和JAXP.在国内比较 ...

  9. Java怎么xml拒绝,Sun Java运行时环境XML解析拒绝服务漏洞

    影响版本: Sun JDK 6 Sun JDK 5.0 Sun JRE 6 Sun JRE 5.0 漏洞描述: BUGTRAQ  ID: 35958 CVE(CAN) ID: CVE-2009-262 ...

  10. java自带的xml解析,使用Java自带SAX工具解析XML

    studentInfo.xml 崔卫兵 PC学院 62354666 男,1982年生,硕士,现就读于北京邮电大学 cwb PC学院 62358888 男,1987年生,硕士,现就读于中国农业大学 xx ...

最新文章

  1. python怎么画两幅图_python matplotlib模块: Subplots(在同一个figure里绘制多个图)
  2. 超详细百家大厂面试资料,免费送!
  3. 五十七、Vue中的八大生命周期函数
  4. Hibernate三大组成部分
  5. Java—List的用法与实例详解
  6. java ee规范_测试Java EE 8规范
  7. java 语义_Java文件合并变得语义化
  8. 展望未来计算机可以分为哪几种类型,大学计算机基础-计算机概述.ppt
  9. 触发JVM进行Full GC的情况及应对策略
  10. python是最好的语言_Python转Crystal语言或许是个不错的选择
  11. 阶段3 2.Spring_06.Spring的新注解_1 spring的新注解-Configuration和ComponentScan
  12. 移动pc一套代码_【腾讯】如何避免 CDN 为 PC 端缓存移动端页面
  13. 80ms 求解世上最难数独 —— DFS的灵活运用
  14. 同济大学Python程序设计基础 实验一:Python程序设计基础
  15. java 获取剪切板文件_如何在Java程序中读写系统剪切板的数据
  16. python爬裁判文书网_对爬取中国裁判文书网的分析
  17. Python随机生成均匀分布在单位圆内的点
  18. 客户端七牛方式上传文件
  19. NLP-准确率、精确率、召回率和F1值
  20. Cesium里面的气泡

热门文章

  1. 12306bycloud,免费开源抢票软件,无需安装,全平台可用
  2. 马哥python培训如何
  3. 2019马哥python的百度网盘_马哥 2018 Python 全栈视频
  4. Web渗透测试学习路线图
  5. ubuntu16.04 更新pip
  6. svn将本地项目传到svn
  7. MT4MT5跟单EA系统跨平台
  8. 机房巡检为什么检查指示灯_小工具需要“检查引擎”指示灯
  9. CppCheck C++静态代码检查工具在Visual Studio(VS)下的配置和使用
  10. 机器学习-DBSCAN密度聚类