估计是个轮子,因为一说起XML,自然想到的是JDom/dom4j等老牌/强大的工具.

但我的需求如此简单: “支持简单的路径求值” ,就加一个N多垃圾的jar包,算了,一气之下,写了这个工具类.

原本这个工具类包含 一个接口,一个实现类,一个工厂类,一个测试类

完成初版后,发现,为啥还分这么多东西,不就一个简单需求嘛!! 很不符合我的风格. 而且,我还特意建了一个工程叫NutzXML ….

不行,这种需要扩展,不考虑效率的东西, 咋调用一下都这么麻烦? 改!!

最后,整个XmlMap类,加上注释,150行, 这里展示的是无注释的版本:

package org.nutz.xml;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class XmlMap{

    private Element element;

    public XmlMap(Element element) {
        this.element = element;
    }

    public List getList(String name) { //这里去掉了泛型,请自行加上
        NodeList nList = element.getElementsByTagName(name);
        List list = new ArrayList(nList.getLength());//这里去掉了泛型,请自行加上
        for (int i = 0; i < nList.getLength(); i++) {
            list.add(new XmlMap((Element)nList.item(i)));
        }
        return list;
    }

    /**
     * 获取一个属性的值
     */
    protected String get(String name) {
        if (element.hasAttribute(name))
            return element.getAttribute(name);
        else if ("value".equals(name))
            return element.getTextContent();
        return null;
    }

    static DocumentBuilder db;

    static {
        try {
            db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 从输入流读取XML文件,构建XmlMap对象
     * @param is 包含Xml文件的输入流
     * @return XmlMap对象
     */
    public static final XmlMap read(InputStream is) {
        try {
            Document doc = db.parse(is);
            doc.normalizeDocument();
            return new XmlMap((Element) doc.getDocumentElement());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static final Object parse(XmlMap map,String path) {
        if (path.indexOf('.') > 0)
            return parse(get2(map, path.substring(0,path.indexOf('.'))), path.substring(path.indexOf('.')+1));
        //到这里的话,应该只剩下 abc#attr 或者abc[12]#attr 或者 abc[12] 或者abc
        if (path.indexOf('#') > -1) //需要获取具体的属性值
            if (path.indexOf('#') > 0)
                return get2(map, path.substring(0,path.indexOf('#'))).get(path.substring(path.indexOf('#')+1));
            else
                return map.get(path.substring(1));
        else
            //如果指定了索引则返回XmlMap,否则返回List
            return path.indexOf('[') > 0 ? get3(map, path) : map.getList(path);
    }

    private static final XmlMap get2(XmlMap map, String path) {
        return path.indexOf('[') > 0 ? get3(map, path) : map.getList(path).get(0);
    }

    private static final XmlMap get3(XmlMap map, String path) {
        return map.getList(path.substring(0,path.lastIndexOf('['))).get(Integer.parseInt(path.substring(path.lastIndexOf('[')+1,path.length()-1)));
    }
}

点击查看完整版 – 在Nutz Lab项目中

使用示例:

 XmlMap map = XmlMap.read(new FileInputStream("demo.xml"));获取XmlMap对象
 map.get("authBy");                       //返回值为xxxUserSeriver
 XmlMap.parse(map, "#authBy");            //返回值为xxxUserSeriver
 XmlMap.parse(map, "other#value");        //other没有value属性,则返回其文本值abc
 XmlMap.parse(map, "url[3]#pattern");     //获取第4个(索引值为3)url标签的pattern属性
 XmlMap.parse(map, "levelA.levelB.levelC[1].levelD#key");//返回值为XX2X
 XmlMap.parse(map, "levelA.levelB");      //返回值为一个包含全部levelB节点的List
 XmlMap.parse(map, "levelA.levelB[1]");   //返回值为第2个levelB节点的XmlMap
 XmlMap.parse(map, "levelA.levelB#myKey");//返回值为nutz

其实,我是打算做一个基于URL的权限控制, 考虑叫NutzSecurity 设想中,YY中



blog comments powered by Disqus

Published

2011-03-06 19:57:55

Categories


Tags

Fork me on GitHub