因为老师的需求,需要实现元信息管理,管理下拉框的所有信息,为了能够更快速地加载下拉框采用了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的操作,当时还真的是成就感满满毕竟攻克自己觉得好难的一个需求。