使用DocumentBuilderFactory来解析xml文件
首先是主函数代码:
public static void main(String[] args) {
try {
final Document xml = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(Main.class.getResourceAsStream("/actions.xml"));
Reader reader = new Reader();
reader.load(new Entry(xml.getDocumentElement()));
} catch (final IOException e) {
} catch (final SAXException e) {
}catch (final ParserConfigurationException e) {
}
}
这里使用了DocumentBuilderFactory::newInstance()获取了一个DocumentBuilderFactory实例。
然后调用DocumentBuilderFactory::newDocumentBuilder()官方文档的描述如下:
Creates a new instance of a DocumentBuilder using the currently configured parameters.
然后使用DocumentBuilder::parse(String uri) parse一个xml文件,结果是返回一个Document实例,同时这个方法需要捕捉IO和SAX异常,
其中的SAXException时parse发生错误时会抛出的错误。
在进行xml的解析之前,我们先来看看Document的定义
Interface Document extends node
因此包括node的方法我们都是可以使用的,那么实际在解析一个xml文件的时候,我们经常需要进行的操作大致为一下几种,
1.获取当前node的tagname
2.获取当前node的attributes
3.选中当前node下的特定child node
4.获取当前node下的child List<node>
所以我们可以定义一个类来给所有的node添加这种通用的特性
static class Entry {
private Element element;
private Map<String, String> attributes;
private List<Entry> children;
private Map<String, List<Entry> > selected = new HashMap<String, List<Entry> >();
public Entry(final Element element) {
this.element = element;
}
public String getName() {
return this.element.getTagName();
}
public Map<String, String> getAttributes() {
if(this.attributes != null) {
return this.attributes;
}
this.attributes = new LinkedHashMap<String, String >();
final NamedNodeMap attrs = this.element.getAttributes();
for(int i = 0; i < attrs.getLength(); ++i ) {
final Attr attr = (Attr)attrs.item(i);
this.attributes.put(attr.getName(), attr.getValue());
}
return this.attributes;
}
public String getAttribute(final String attributeName) {
final Attr attribute = this.element.getAttributeNode(attributeName);
if (attribute == null) {
return null;
}
return attribute.getValue();
}
public List<Entry> selectChildren(final String tagName) {
List<Entry> children = this.selected.get(tagName);
if ( children!=null ) {
return children;
}
children = new ArrayList<Entry>();
for( final Entry child : getChildren() ) {
if ( child.getName().equals(tagName)) {
children.add(child);
}
}
this.selected.put(tagName, children);
return children;
}
public List<Entry> getChildren() {
if ( this.children!=null) {
return this.children;
}
this.children = new ArrayList<Entry>();
final NodeList childNodes = this.element.getChildNodes();
for( int i = 0; i<childNodes.getLength(); ++i) {
final Node childNode = childNodes.item(i);
if ( childNode instanceof Element ) {
this.children.add(new Entry((Element)childNode));
}
}
return this.children;
}
}
这里我使用的时shimeji里面实现Entry类,然后我们创建一个Reader类来试着读取某个xml的参数
static class Reader {
private final Map<String, String> constants = new LinkedHashMap<String, String>();
public void load(final Entry configurationNode) throws IOException {
for (final Entry constant : configurationNode.selectChildren("定数")) {
System.out.println("constant is: " + constant.getAttribute("値"));
constants.put( constant.getAttribute("名前"), constant.getAttribute("値") );
}
for (final Entry list : configurationNode.selectChildren("動作リスト")) {
for (final Entry node : list.selectChildren("動作")) {
System.out.println("node name is: " + node.getName());
}
}
for (final Entry list : configurationNode.selectChildren("行動リスト")) {
System.out.println("list name is: " + list.getName());
loadBehaviors(list, new ArrayList<String>());
}
}
private void loadBehaviors(final Entry list, final List<String> conditions) {
for (final Entry node : list.getChildren()) {
if (node.getName().equals("条件")) {
final List<String> newConditions = new ArrayList<String>(conditions);
newConditions.add(node.getAttribute("条件"));
loadBehaviors(node, newConditions);
} else if (node.getName().equals("行動")) {
System.out.println("action is: " + node.getName());
}
}
}
}
下面附上运行结果
这段代码已经上传到:
https://github.com/AlanJager/java_learning