package xml_util;
import java.io.File;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* 这里我的想法:是抛砖引玉,渴望大家提出更好和不足建议
* 工具类只提供遍历操作,不提供增删操作
* 在Dom xml增删操作中只是在内存中进行的
* 在xml文档中我们是看不出的,在增删操作之后必须重新输出xml文档之后,才可以看到结果
* @author kevin.wangwei
* 2010-4-5
*/
public final class XmlUtil {
/** xml 文档对象 */
private Document document;
/** 工具类单例对象 */
private static XmlUtil instance;
/** xml在系统中的路径 */
private String xmlFilePath;
/**xml 根元素名称 */
private String documentElementName;
private XmlUtil(String xmlFilePath)throws Exception{
this.xmlFilePath=xmlFilePath;
readXmlDocument();
}
public String getXmlFilePath() {
return xmlFilePath;
}
public String getDocumentElementName() {
return documentElementName;
}
/**
* 获得工具类实例
* @return
*/
public static XmlUtil newInstance(String xmlFilePath) throws Exception{
if(instance==null){
synchronized(XmlUtil.class){
if(instance==null){
instance=new XmlUtil(xmlFilePath);
}
}
}
return instance;
}
/**
* 读取xml文档
* @throws Exception
*/
private void readXmlDocument() throws Exception{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
document=db.parse(new File(xmlFilePath));
Element documentElement=document.getDocumentElement();
if(documentElement!=null){
documentElementName=documentElement.getNodeName();
}
}
/**
* 打印xml文档内容
*/
public String printerXmlDocument(){
StringBuffer sb=new StringBuffer();
sb.append("<?xml version=\""+document.getXmlVersion()+"\" encoding=\""+document.getXmlEncoding()+"\" ?>\n");
printerNode(document,sb);
return sb.toString();
}
/**
* 打印文本节点内容
* @param node
*/
private void printerTextNodeInfo(Node node,StringBuffer sb){
if(node==null){
return;
}
String value=StringUtil.validateString(node.getNodeValue());
if(!(value.trim().equals(""))){//除去空白的文本节点
sb.append(value+"\n");
}
}
/**
* 打印属性节点名称和值
* @param node
*/
private void printerAttributesNode(Node node,StringBuffer sb){
if(node==null){
return;
}
NamedNodeMap attrs=node.getAttributes();
int length=attrs.getLength();
for(int i=0;i<length;i++){
Node attr=attrs.item(i);
sb.append(" "+StringUtil.validateString(attr.getNodeName())+"=\""+StringUtil.validateString(attr.getNodeValue())+"\"");
}
}
/**
* 打印xml文档中所有节点
* @param node
* @param sb
*/
private void printerNode(Node node,StringBuffer sb){
if(node==null){
return;
}
NodeList nl=node.getChildNodes();
for(int i=0;i<(nl.getLength());i++){
Node n=nl.item(i);
if(n.getNodeType()==Node.ELEMENT_NODE){
String nodeName=n.getNodeName();
sb.append("<"+n.getNodeName());
printerAttributesNode(n,sb);
sb.append(">\n");
printerNode(n,sb);
sb.append("</"+nodeName+">\n");
}else if(n.getNodeType()==Node.TEXT_NODE){
printerTextNodeInfo(n,sb);
}else if(n.getNodeType()==Node.COMMENT_NODE){
sb.append("<"+n.getNodeName()+">");
printerTextNodeInfo(n,sb);
sb.append("</"+n.getNodeName()+">\n");
}else{
printerTextNodeInfo(n,sb);
}
}
}
/**
* 依据节点名称查找该节点的所有文本节点的值(包括该节点的子节点)
* @param nodeName
* @return
*/
public ArrayList<String> getNodeValue(String nodeName){
if(!StringUtil.isValidateString(nodeName)){
return null;
}
ArrayList<String> values=new ArrayList<String>();
NodeList nl=document.getElementsByTagName(nodeName);
int length=nl.getLength();
for(int i=0;i<length;i++){
Node node=nl.item(i);
if(node.getNodeType()==Node.TEXT_NODE){
String value=StringUtil.validateString(node.getNodeValue());
if(!(value.trim().equals(""))){
values.add(value);
}
}else if(node.getNodeType()==Node.ELEMENT_NODE){
traversalNode(node,values);
}
}
return values;
}
/**
* 递归查找当前节点的所有文本节点
* @param node
* @param values
*/
private void traversalNode(Node node,ArrayList<String> values){
if(node==null){
return ;
}
NodeList nl=node.getChildNodes();
int length=nl.getLength();
for(int i=0;i<length;i++){
Node n=nl.item(i);
if(n.getNodeType()==Node.TEXT_NODE){
String value=StringUtil.validateString(n.getNodeValue());
if(!(value.trim().equals(""))){
values.add(value);
}
}else if(n.getNodeType()==Node.ELEMENT_NODE){
traversalNode(n,values);
}
}
}
/**
* 依据当前元素名称,查找该元素的所有属性
* @param nodeName
* @return
*/
public Map<String,String> getNodeAttributes(String nodeName) throws Exception{
if(!StringUtil.isValidateString(nodeName)){
return null;
}
Map<String,String> map=new HashMap<String,String>();
NodeList nl=document.getElementsByTagName(nodeName);
int length=nl.getLength();
for(int i=0;i<length;i++){
Node node=nl.item(i);
if(node.getNodeType()!=Node.ELEMENT_NODE){
throw new Exception("这不是一个有效节点元素");
}else{
NamedNodeMap attrs=node.getAttributes();
int len=attrs.getLength();
for(int j=0;j<len;j++){
Node attr=attrs.item(j);
map.put(StringUtil.validateString(attr.getNodeName()), StringUtil.validateString(attr.getNodeValue()));
}
}
}
return map;
}
/**
* 依据指定输出流输出xml文档
* @param toFilePath
* @throws Exception
*/
public void transformer(OutputStream out) throws Exception{
TransformerFactory tff=TransformerFactory.newInstance();
Transformer tf=tff.newTransformer();
DOMSource source=new DOMSource(document);
StreamResult result=new StreamResult(out);
tf.transform(source, result);
}
public static void main(String args[]) throws Exception{
XmlUtil xml=XmlUtil.newInstance("d:\\test2.xml");
//System.out.println(xml.printerXmlDocument());
//for(String str:xml.getNodeValue("id")){
// System.out.println(str);
//}
//System.out.println(xml.getNodeAttributes("student"));
//xml.transformer(System.out);
}
}