java解析xml

如下xml为例:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" ?>
<datasoruce>
<property name="driver">com.mysql.jdbc.Driver</property>
<property name="url">
jdbc:mysql://127.0.0.1:3306/poker?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=true
</property>
<property name="username">root</property>
<property name="password">root</property>
</datasoruce>

解析引入dom4j,这里使用的为2.0.0版本,具体文档到社区查看,github已有最新2.0.1版本,dom4j更新很慢,也可以说比较稳定。
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
日志输出使用:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
解析类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class XmlParser
{
private static final Logger logger = LoggerFactory.getLogger(XmlParser.class);
public static HashMap<String, String> parse(InputStream inputStream)
{
SAXReader reader = new SAXReader();
Document document = null;
try
{
document = reader.read(inputStream);
}
catch (DocumentException e)
{
logger.error("parse xml error: {}", e);
}
Element root = document.getRootElement();
List nodes = root.elements("property");
Iterator<Element> it = nodes.iterator();
HashMap<String, String> map = new HashMap<>();
while (it.hasNext())
{
Element element = it.next();
map.put(element.attribute("name").getText(), element.getStringValue());
}
return map;
}
}

外层调用:

1
2
InputStream inputStream = DbManager.class.getResourceAsStream("/datasource.xml");
HashMap<String, String> map = XmlParser.parse(inputStream);

另外,如果验证拿到xml的合法性,则如下,将输入流解析为字符流输出,引入com.google.common.io.CharStreams;

1
2
3
4
5
6
7
8
9
10
// 输出连接数据库的配置文件
InputStream inputStream = DbManager.class.getResourceAsStream("/datasource.xml");
try {
String text = CharStreams.toString(new InputStreamReader(inputStream, "UTF-8"));
logger.info("dataSource.xml str: \n{}",text);
} catch (IOException e) {
logger.error("dataSource.xml IOException e ->{}", e);
}
inputStream = DbManager.class.getResourceAsStream("/datasource.xml");
HashMap<String, String> map = XmlParser.parse(inputStream);

String text = CharStreams.toString(new InputStreamReader(inputStream, “UTF-8”));已经将输入流读取完毕,已到流的结尾,不可直接再次使用。需重新获取inputStream = DbManager.class.getResourceAsStream(“/datasource.xml”);

补充,上一步执行了两次
inputStream = DbManager.class.getResourceAsStream(“/datasource.xml”);
效率很低,看起来也很傻。又看了下inputStream有mark/reset方法,解决了我的问题。如下:

1
2
3
4
5
6
7
8
9
10
11
inputStream = DbManager.class.getResourceAsStream("/datasource.xml");
try {
// inputStream.markSupported();
inputStream.mark(inputStream.available());
String text = CharStreams.toString(new InputStreamReader(inputStream, "UTF-8"));
inputStream.reset();
logger.info("dataSource.xml str: \n{}",text);
} catch (IOException e) {
logger.error("dataSource.xml IOException e ->{}", e);
}
HashMap<String, String> map = XmlParser.parse(inputStream);

InputStream本身提供三个接口

  • markSupported();InputStream是否支持mark,默认不支持
  • mark(int readLimit);用于标记当前位置,在读取一定数量的数据(小于readlimit的数据)后使用reset可以回到mark标记的位置。
  • reset();回到mark标记位置。

子类需要支持mark必须重写这三个方法。