因为老师的需求,需要实现元信息管理,管理下拉框的所有信息,为了能够更快速地加载下拉框采用了xml存储的形式,其实我本来对xml的操作一窍不通,只知道大致的写法,但是真的要操作这块还真的有点难度。经过一番百度谷歌总算实现了需求。

首先,xml的写法是成功的一半,原本我的xml写法大致如下(尖括号内为相应英文,为了表述方便用中文):

<产品类别>
  <子项>饮料</子项>
  <子项>饼干</子项>
</产品类别>

于是我在查看了大部分的操作xml文件的xml写法大多都类似:

<班级> 
  <学生 sex="男"> 
    <名字 sex="男">宋江</名字>  
    <年龄>23</年龄>  
    <介绍>刻苦学习</介绍> 
  </学生>  
  <学生 sex="女"> 
    <名字>林青霞</名字>  
    <年龄>32</年龄>  
    <介绍>是一个好学生</介绍> 
  </学生>
  <学生>林冲</学生> 
</班级>

后面我就觉得这样的写法可能很难操作,所以更改了写法,改成如下的统一形式:

<drop_list>
    <dropList name="行业类别">
        <item>批发业</item>
        <item>零售业</item>
    </dropList>
    <dropList name="企业性质">
        <item>国有</item>
        <item>民营</item>
    </dropList>
<drop_list>
 

之后的操作就是照猫画老虎,但是还有一个问题就是如何选择操作方式,是使用dom还是sax还是dom4j、Jdom。我尝试了dom4j但是由于他的一些函数没办法满足我的需求就抛弃了,转用最初始的dom操作且不需要导入新的包。

private static DocumentBuilderFactory documentBuilderFactory=null;
private static DocumentBuilder documentBuilder=null;
private static Document document=null;
public static Map<String, ArrayList<String>> getAllDropList() {
    Map<String ,ArrayList<String>> dropMap=new HashMap<String, ArrayList<String>>();
     String key = null;

    //1、创建一个DocumentBuilderFactory的对象
    documentBuilderFactory=DocumentBuilderFactory.newInstance();
    try {
        //2、创建一个DocumentBuilder的对象
        documentBuilder=documentBuilderFactory.newDocumentBuilder();
        //3、通过DocumentBuilder对象的parser方法加载xml文件到当前项目下
        /注意导入Document对象时,要导入org.w3c.dom.Document包下的/
        //获取路径
        WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
        ServletContext servletContext = webApplicationContext.getServletContext();
        document=documentBuilder.parse("file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml");
        NodeList nodeList = document.getElementsByTagName("dropList");
        //通过nodelist的getlenght方法获取nodelist的长度
        //遍历每一个nodelist节点
        for (int i = 0; i < nodeList.getLength(); i++)
        {
            //未知节点属性的个数和属性名时:
            //通过 item(i)方法 获取一个dropList节点,nodelist的索引值从0开始
            Node dropNode=(Element)nodeList.item(i);
            //获取所有book节点的属性集合
            NamedNodeMap attrs=dropNode.getAttributes();
          //  System.out.println("第 " + (i + 1) + "下拉框共有" + attrs.getLength() + "个属性");
            //遍历所有的属性
            for (int j = 0; j < attrs.getLength(); j++) {
                //通过item(index)方法获取节点的某一个属性
                Node attr = attrs.item(j);
                //获取属性值
                key=attr.getNodeValue();
            }
            //解析子节点
            NodeList childNodes = dropNode.getChildNodes();
            //遍历childNodes获取每个节点的节点名和节点值
            ArrayList<String> drop_list=new ArrayList<String>();
            for (int k = 0; k < childNodes.getLength(); k++) {
                //区分出text类型的node以及element类型的node
                if(childNodes.item(k).getNodeType() == Node.ELEMENT_NODE){
                    //获取了element类型节点的节点名
                    //获取了element类型节点的节点值
                    drop_list.add(childNodes.item(k).getFirstChild().getNodeValue());
                }
            }
            dropMap.put(key,drop_list);

        }
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return dropMap;
}

如上就是显示整个xml的展示代码,由于项目需要跑在tomcat上所以需要得到相应的路径。

之后就是获取某个节点,然后遍历属性或者节点。因为只有2层,原型是需要表格显示整个xml,故而思考如何把它输出,因为只有两层,所以采用了Map<String, ArrayList<String>>的结果集。以每个节点的属性名作为key,每个节点的子节值作为list存储,输出到前端,前端采用angularjs,采用两个表格的生成形式来显示,第一列为属性名即key,第二列的每一行都会再嵌入一个表格输出list的每个节点值。

增删改:

//新增
public  static  void createSon(String key,String sonNode){
    WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
    ServletContext servletContext = webApplicationContext.getServletContext();
     //String xmlPath="src\main\webapp\logistics\js\xml\drop_list.xml";
    String xmlPath="file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml";
    //document=documentBuilder.parse("file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml");
    // 创建文件工厂实例
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setIgnoringElementContentWhitespace(false);
    String nodeKey=key;

    try {

        DocumentBuilder db = dbf.newDocumentBuilder();
        // 创建Document对象
        Document xmldoc = db.parse(xmlPath);
        // 获取根节点
        Element root = xmldoc.getDocumentElement();
        // 创建节点son,设置对应的id为004
        //Element son = xmldoc.createElement("dropList");
        //son.setAttribute("name", "004");
        Element son=(Element) selectSingleNode("/drop_list/dropList[@name='"+nodeKey+"']", root);
        // 创建节点name
        System.out.println("/drop_list/dropList[@name='"+nodeKey+"']");
        Element name = xmldoc.createElement("item");
        name.setTextContent(sonNode);
        //name.setAttribute("code",sonAtt);
        son.appendChild(name);

        // 把son添加到根节点中
        // 保存
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer former = factory.newTransformer();
        former.transform(new DOMSource(xmldoc), new StreamResult(xmlPath));

    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

//修改属性值
public  static  void updateNode(String nodeKey,String newNodeKey){
    WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
    ServletContext servletContext = webApplicationContext.getServletContext();
    //String xmlPath="src\main\webapp\logistics\js\xml\drop_list.xml";
    String xmlPath="file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml";
    //document=documentBuilder.parse("file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml");
    // 创建文件工厂实例
    DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
    dbf.setIgnoringElementContentWhitespace(true); //是否删除空格  false true
    try {
        //从xml文件中获取DOM文档实例
        DocumentBuilder db=dbf.newDocumentBuilder();
        //获取document对象
        Document xmldoc=db.parse(xmlPath);
        //获取根节点
        Element root=xmldoc.getDocumentElement();
        //定位属性name为传进来的参数的节点
        Element per=(Element)selectSingleNode("/drop_list/dropList[@name='"+nodeKey+"']", root);
        //修改属性key为i????
        per.setAttribute("name",newNodeKey);
        //保存
        TransformerFactory factory=TransformerFactory.newInstance();
        Transformer transformer=factory.newTransformer();
        transformer.transform(new DOMSource(xmldoc),new StreamResult(xmlPath));
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }


}

//修改子节点的名字
public static void updateSonNode(String parentKey, String newSon, int sonNum) {
    WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
    ServletContext servletContext = webApplicationContext.getServletContext();
    //String xmlPath="src\main\webapp\logistics\js\xml\drop_list.xml";
    String xmlPath = "file:///" + servletContext.getRealPath("/logistics/js/xml") + "/drop_list.xml";
    //document=documentBuilder.parse("file:///"+servletContext.getRealPath("/logistics/js/xml")+"/drop_list.xml");
    // 创建文件工厂实例
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setIgnoringElementContentWhitespace(true); //是否删除空格  false true
    try {
        // 从XML文档中获取DOM文档实例
        DocumentBuilder db = dbf.newDocumentBuilder();
        // 获取Document对象
        Document xmldoc = db.parse(xmlPath);

        // 获取根节点
        Element root = xmldoc.getDocumentElement();
        //定位节点
        Element per=(Element)selectSingleNode("/drop_list/dropList[@name='"+parentKey+"']", root);
        per.getElementsByTagName("item").item(sonNum).setTextContent(newSon);

        TransformerFactory factory=TransformerFactory.newInstance();
        Transformer transformer=factory.newTransformer();
        transformer.transform(new DOMSource(xmldoc),new StreamResult(xmlPath));

    }catch (Exception e){
        System.out.println(e.getMessage());
    }
}
//删除子节点 不允许删除父节点
public static void delSonNode(String parentKey,int sonNum){
    WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
    ServletContext servletContext = webApplicationContext.getServletContext();
    //String xmlPath="src\main\webapp\logistics\js\xml\drop_list.xml";
    String xmlPath = "file:///" + servletContext.getRealPath("/logistics/js/xml") + "/drop_list.xml";
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setIgnoringElementContentWhitespace(true);
    try {
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document xmldoc = db.parse(xmlPath);
        // 获取根节点
        Element root = xmldoc.getDocumentElement();
        // 定位根节点中的name=parentKey的节点
        Element per=(Element)selectSingleNode("/drop_list/dropList[@name='"+parentKey+"']", root);
        // 删除该节点
       Element son=(Element) per.getElementsByTagName("item").item(sonNum);
       per.removeChild(son);
        //root.removeChild( per.getElementsByTagName("item").item(sonNum));
        // 保存
        TransformerFactory factory=TransformerFactory.newInstance();
        Transformer transformer=factory.newTransformer();
        transformer.transform(new DOMSource(xmldoc),new StreamResult(xmlPath));
    }catch (Exception e){
        System.out.println(e.getMessage());
    }

}
public static Node selectSingleNode(String express, Element source) {
    Node result = null;
    //创建XPath工厂
    XPathFactory xpathFactory = XPathFactory.newInstance();
    //创建XPath对象
    XPath xpath = xpathFactory.newXPath();
    try {
        result = (Node) xpath.evaluate(express, source, XPathConstants.NODE);
        System.out.println(result);
    } catch (XPathExpressionException e) {
        System.out.println(e.getMessage());
    }

    return result;
}

参考了几个博客才搞定这个xml的操作,当时还真的是成就感满满毕竟攻克自己觉得好难的一个需求。