新项目里面解析xml需要sax,就查了下资料,顺便写点加强理解。xml中有两种节点,一种是ElementNode,比如下面的一个简单的xml文件中的<SkillInfo>和<skill>等,另一种是TextNode,是节点之间的文本(例如<name>测试解析xml</name>中的测试解析xml就是TextNode)。
sax解析器是将xml文件按照顺序依次载入,当读到<SkillInfo>这些Element节点时,就会调用startElemt(……)方法,节点之间的空白sax解析器认为是TextNode节点,只是是空的,节点之间的文本会调用characters(……)方法,不过本文没用到。当解析到</……>这种标签时,会调用endElement(……)方法。
看看如下简单xml文件的解析代码,将<skill>节点的数据放到map中保存,id为key,value是一个类对象,类中含有属性id,addtional和name。
xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<SkillInfo>
<skill id="1" addtional="攻击目标数最多可升阶至7个" name="虎啸">
<upgrade>
<node level="0" desc="升阶提升技能攻击范围和目标数">
<effect type="1" effect="208"/>
</node>
</upgrade>
</skill>
</SkillInfo>
java代码:
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import java.util.*;
public class TestJavaSax extends DefaultHandler {
/**
* 解析时ElementNode调用startElement,
* @param qName就是节点名
* @param attr就是对应标签的所有属性,通过attr.getValue("属性名")取得属性数据
*/
public void startElement(String namespaceURI, String localName, String qName, Attributes attr ) throws SAXException {
if ("skill_info".equals(qName)) {
//……
}
else if ("skill".equals(qName)) {
//_tmpSkillItem保存相应标签的属性值
_tmpSkillItem = new SkillItem();
_tmpSkillItem.setId(Integer.parseInt(attr.getValue("id")));
_tmpSkillItem.setAddtional(attr.getValue("addtional"));
_tmpSkillItem.setName(attr.getValue("name"));
}
else if ("upgrade".equals(qName)) {
//……
}
else if ("node".equals(qName)) {
_tmpNodeItem = new NodeItem();
_tmpNodeItem.setLevel(Integer.parseInt(attr.getValue("level")));
_tmpNodeItem.setDesc(attr.getValue("desc"));
}
else if ("effect".equals(qName)) {
//……
}
}
/**
* 解析TextNode时回调,此次没用到
*/
public void characters( char[] chars, int start, int length ) throws SAXException {
//……
}
/**
* 遇到结束标签时回调
* @param qName是标签名
*/
public void endElement( String namespaceURI, String localName, String qName ) throws SAXException {
if ("skill_info".equals(qName)) {
//……
}
else if ("skill".equals(qName)) {
skillDict.put(_tmpSkillItem.getId(), _tmpSkillItem); //将属性对象放到map中
_tmpSkillItem = null; //去掉不必要的引用
}
else if ("upgrade".equals(qName)) {
//……
}
else if ("node".equals(qName)) {
//……
_tmpNodeItem = null;
}
}
public static TestJavaSax getInstance() {
if (null == saxInstance) {
saxInstance = new TestJavaSax();
//实例化用于分析的工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
//实例化分析类
SAXParser parser = factory.newSAXParser();
//xml路径
String path = "skill_info.xml";
parser.parse(path, saxInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
return saxInstance;
}
public static void main(String[] args) {
TestJavaSax saxInstance = TestJavaSax.getInstance();
Iterator iter = skillDict.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
SkillItem tmpClass = new SkillItem();
tmpClass = (SkillItem)entry.getValue();
System.out.print("key:" + entry.getKey() + " ");
System.out.println("value:" + tmpClass.getId() + ", " + tmpClass.getAddtional() + ", " + tmpClass.getName());
}
}
private static TestJavaSax saxInstance = null;
private SkillItem _tmpSkillItem = null;
private NodeItem _tmpNodeItem = null;
private static Map<Integer, SkillItem> skillDict = new HashMap<Integer, SkillItem>();
}
/**
* SkillItem保存属性值
*/
class SkillItem {
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setAddtional(String addtional) {
this.addtional = addtional;
}
public String getAddtional() {
return addtional;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
private int id;
private String addtional;
private String name;
}
class NodeItem {
public void setLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
private int level;
private String desc;
}
控制台打印的部分解析结果:
key:1 value:1, 攻击目标数最多可升阶至7个, 虎啸