XMLParse之XML文件解析实现
第一篇已经介绍了基础的
XMLAttribute
、XMLBase
、XMLNoChilds
、XMLHasKids
四个类的设计,接下来我们根据上面四个类进行XML文件的解析。
提示,在解析XML时用到了第三方的dom4j.jar
导入即可(站在巨人肩膀上真的很好)。
<Books type="文艺">
<Book name="西游记"/>
<Book name="红楼梦"/>
</Books>
我们用JAVA这样描述:
class Book{
private String name;
//构造方法和get set
}
class Books{
private String type;
private List<Book> books;
//构造方法和get set
//注意,在构造方法中要实现books的实例化
}
这两种类称为XML标签类
将这两个XML标签类
放到指定位置就可以通过反射找到他们,然后在调用transform()
进行转换
XML解析过程
读取文件
通过
dom4j.jar
进行读取,本人用的是SAXReader来进行读取。
生成XMLBase
在
XMLReader.java
中定义了XMLparse()
方法,其中用到了递归处理,因为子标签也可能有子标签,递归结束标志就是当前标签是无子标签。
public static void XMLparse(Element rootElement,XMLBase root){
XMLBase cur;
//判断标签元素是否还有子元素
if (rootElement.elements().size()>0){
//含有子元素,创建XMLBase
cur = new XMLHasKids(rootElement.getName());
//给XMLBase中的属性集合赋值
List<Attribute> attributes = rootElement.attributes();
List<XMLAttribute> xmlAttributes = new ArrayList<>();
for (Attribute attribute : attributes) {
xmlAttributes.add(new XMLAttribute(attribute.getName(),attribute.getValue()));
}
cur.setXMLAttributes(xmlAttributes);
//将新创建的XMLBase添加到上一级的子标签集合中
root.addKids(cur);
//对子元素的子元素进行递归赋值
List<Element> childelement = rootElement.elements();
for (Element element : childelement) {
XMLparse(element,cur);
}
}else {
//当没有子元素时,创建XMLBase对象
cur = new XMLNoChilds(rootElement.getName());
//给XMLBase对象中的属性集合赋值
List<Attribute> attributes = rootElement.attributes();
List<XMLAttribute> xmlAttributes = new ArrayList<>();
for (Attribute attribute : attributes) {
xmlAttributes.add(new XMLAttribute(attribute.getName(),attribute.getValue()));
}
cur.setXMLAttributes(xmlAttributes);
//将新创建的XMLBase添加到上一级的子标签集合中
root.addKids(cur);
}
}
transform转换
对于已经生成XMLBase的XML文件,只需要调用XMLBase的
transform()
方法就能获得对应的XML标签类
实例。此方法已经封装到了XMLAPI.java
中。
/**
* Read xml object.
*
* @param inputStream the input stream of xml file
* @return the object
*/
public static Object readXML(InputStream inputStream){
Element rootElement = null;
SAXReader reader = new SAXReader();
try {
document = reader.read(inputStream);
} catch (DocumentException e) {
e.printStackTrace();
}
//先 将root 节点解析出来
if (document != null)rootElement = document.getRootElement();
XMLBase root = new XMLHasKids(rootElement.getName());
List<Attribute> attributes = rootElement.attributes();
List<XMLAttribute> xmlAttributes = new ArrayList<>();
for (Attribute attribute : attributes) {
xmlAttributes.add(new XMLAttribute(attribute.getName(),attribute.getValue()));
}
root.setXMLAttributes(xmlAttributes);
//利用递归 将子节点逐一解析 放入xmlbase 中
List<Element> childelement = rootElement.elements();
for (Element element : childelement) {
XmlReader.XMLparse(element,root);
}
return root.transform();
}
最后说一下,上一篇中XMLBase抽象类中是定义了一个方法valueFormat()
是在transform()
时对属性进行赋值的,现在贴出来,当然还有很多需要优化的地方。
/**
*数值转换方法,根据不同的数值类型将值传入
*关键是异常捕获后的赋值,避免赋值出现空值
*/
protected void valueFormat(String type,Object o,XMLAttribute XMLAttribute,Method method) throws InvocationTargetException, IllegalAccessException {
if (type.contains(".String")){
method.invoke(o,XMLAttribute.getValues());
}else if (type.contains(".Integer")){
Integer values;
try {
values = Integer.valueOf(XMLAttribute.getValues());
}catch (NumberFormatException e){
e.printStackTrace();
values = 0;
}
method.invoke(o,values);
}else if (type.contains(".Float")){
Float values;
try {
values = Float.valueOf(XMLAttribute.getValues());
}catch (NumberFormatException e){
values = 0.0f;
e.printStackTrace();
}
method.invoke(o,values);
}else if(type.contains(".Boolean")){
Boolean values;
values = Boolean.valueOf(XMLAttribute.getValues());
method.invoke(o,values);
}
}