XML解析

1.JAVA解析XML的方式

  • DOM解析

標準由W3C定義,java有實現(jaxp)。DOM方式是把整個XML文件在內存中生成一顆倒置的樹,樹的節點就是XML文件的元素。DOM的方式解析XML使用起來簡單,能夠從樹的根節點方便的訪問到任何一個XML的元素,但因爲DOM方式須要在內存裏完整的加載和生成一棵樹,若是XML過大,效率相對較低。java

public class ParseByDom {	
	public void parse(Document document){
		//獲取文檔的根元素
		Element root = document.getDocumentElement();
		//獲取根元素下,全部的子元素
		NodeList nodes = root.getChildNodes();
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			//判斷當前節點是否是一個標籤元素
			if(node.getNodeType() == Node.ELEMENT_NODE){
				//獲取當前節點中全部的屬性集合
				NamedNodeMap map = node.getAttributes();
				//取得屬性值爲no的Node表示形式
				Node n = map.getNamedItem("no");
				//獲取屬性對應的值
				String value = n.getNodeValue();
				System.out.println("no:"+value);
				//獲取book節點下全部子節點
				NodeList list = node.getChildNodes();
				for (int j = 0; j < list.getLength(); j++) {
					Node n2 = list.item(j);
					if(n2.getNodeType() == Node.ELEMENT_NODE){
						//得到文本值
						String text = n2.getTextContent();
						//判斷節點名字
						if(n2.getNodeName().equals("name")){
						}else if(n2.getNodeName().equals("author")){
							System.out.println("author:"+text);
						}else if(n2.getNodeName().equals("publish")){
							System.out.println("publish:"+text);
						}else if(n2.getNodeName().equals("price")){
							System.out.println("price:"+text);
						}
					}
				}
				System.out.println("-------------------------");
			}
		}
	}
	public void parse2(Document document){
		//根據標籤名得到標籤
		NodeList nodes = document.getElementsByTagName("book");
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			//取出屬性no
			String no = node.getAttributes().getNamedItem("no").getNodeValue();
			System.out.println("no:"+no);
			//取出子節點
			NodeList list = node.getChildNodes();
			for (int j = 0; j < list.getLength(); j++) {
				//判斷子節點類型
				if(list.item(j).getNodeType() == Node.ELEMENT_NODE){
					System.out.println(list.item(j).getNodeName()+":"+list.item(j).getTextContent());
				}
			}
			System.out.println("--------------------------------");
		}
	}
	public static void main(String[] args) {
		//先得到解析器工廠
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			//獲取解析器
			DocumentBuilder builder = factory.newDocumentBuilder();
			//解析指定源,並得到文檔對象
			Document document = builder.parse(new File("src/book.xml"));
			//調用parse方法
			new ParseByDom().parse2(document);
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • SAX解析

SAX處理的優勢很是相似於流媒體的優勢。分析可以當即開始,而不是等待全部的數據被處理。並且,因爲應用程序只是在讀取數據時檢查數據,所以不須要將數據存儲在內存中,這對於XML文件過大時是有好處的,可是,SAX解析器的時候編碼工做會比較困難,並且很難同時訪問同一個文檔中的多處不一樣數據。node

public class ParseBySax extends DefaultHandler {
	/**
	 * 文檔開始
	 */
	public void startDocument() throws SAXException {
		System.out.println("開始解析");
	}
	/**
	 * 標籤開始
	 */
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		String s = "<" + qName;
		for(int i = 0; i < attributes.getLength();i++){
			String attrName = attributes.getQName(i);
			String attrValue = attributes.getValue(i);
			s += " " + attrName + "=\"" + attrValue + "\"";
		}
		s += ">";
		System.out.print(s);
	}
	/**
	 * 標籤中的文本
	 */
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		System.out.print(new String(ch,start,length));
	}
	/**
	 * 標籤結束
	 */
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.print("</"+qName+">");
	}
	/**
	 * 結束解析
	 */
	public void endDocument() throws SAXException {
		System.out.println();
		System.out.println("結束解析");
	}
	public static void main(String[] args) {
		//建立解析器工廠
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//獲取解析器
		try {
			SAXParser parser = factory.newSAXParser();
			parser.parse(new File("src/book.xml"), new ParseBySax());
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • JDOM解析(專門針對JAVA)

JDOM是一個開源項目(http://www.jdom.org),它基於樹形結構,利用純java技術對XML文檔實現解析、生成、序列化以及多種操做。JDOM直接爲JAVA編程服務。它利用更爲強有力的JAVA語言的諸多特性(方法重載、集合概念以及映射),把SAX和DOM的功能有效的結合起來。 使用時須要導入jdom.jar包(固然若是用maven的話,直接在maven中添加相關依賴是能夠的)mysql

import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class ParseByJDom {
	public static void main(String[] args) {
		//得到解析器
		SAXBuilder builder = new SAXBuilder();
		try {
			//解析文件獲取文檔對象
			Document documnet = builder.build(new File("src/book.xml"));
			//獲取文檔根元素
			Element root = documnet.getRootElement();
			//獲取全部的book節點
			List list = root.getChildren("book");
			for (int i = 0; i < list.size(); i++) {
				Element ele = (Element)list.get(i);
				//獲取當前節點屬性的值
				String no = ele.getAttributeValue("no");
				//獲取當前節點下面子節點的值
				String name = ele.getChild("name").getText();
				String author = ele.getChildText("author");
				String publish = ele.getChildText("publish");
				String price = ele.getChildText("price");
				System.out.println(no+"=="+name+"=="+publish+"=="+author+"=="+price);
			}
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • DOM4J解析(專門針對JAVA)

DOM4J(http://dom4j.sourceforge.net)最開始是JDOM的一個分支,也是一款優秀的JAXP,使用起來很是簡單。sql

> **如今咱們來舉一個例子,模仿hibernate解析xml,用於數據庫鏈接,並生成相應的表**
1. xml文件以下(hibernate.cfg.xml和Student.hb.xml)
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-configuration>
	<session-factory>
		<property name="connection.jdbc_driver">com.mysql.jdbc.Driver</property>
		<property name="connection.url">jdbc://mysql://localhost:3306/mysql</property>
		<property name="connection.username">**</property>
		<property name="connection.password">***</property>
		<mapping resource="Student.hbm.xml"/>
	</session-factory>
</hibernate-configuration>
<hibernate-mapping>
	<class name="Student" table="students">
		<id name="sid" column="stu_id" type="number" length="4"></id>
		<property name="sname" type="varchar" length="20"></property>
		<property name="sex" type="varchar" length="2"></property>
		<property name="birthday" type="date"></property>
		<property name="major" type="varchar" length="20"></property>
	</class>
</hibernate-mapping>
1. 建立一個Config類,Cofig對象中存放數據庫鏈接以及mapping的信息
public class Config {
	private String driver;
	private String url;
	private String username;
	private String password;
	private List<String> mappings;
	public String getDriver() {
		return driver;
	}
	public void setDriver(String driver) {
		this.driver = driver;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public List<String> getMappings() {
		return mappings;
	}
	public void setMappings(List<String> mappings) {
		this.mappings = mappings;
	}
	@Override
	public String toString() {
		return "Config [driver=" + driver + ", mappings=" + mappings
				+ ", password=" + password + ", url=" + url + ", username="
				+ username + "]";
	}
}
3. 下面咱們開始用dom4j解析hibernate.cfg.xml
public class HibernateConfiguration {
	private Config cfg;
	//指定默認文件的構造器
	public HibernateConfiguration(){
		this("src/hibernate.cfg.xml");
	}
	//指定本身定義文件名字的構造器
	public HibernateConfiguration(String file){
		 init(file);
		 System.out.println(cfg);
	}
	public void init(String file){
		cfg = new Config();
		//獲取解析器
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File(file));
			//獲取全部的property節點
			List<Node> nodes = document.selectNodes("hibernate-configuration/session-factory/property");
			for (Node node : nodes) {
				String name = node.valueOf("@name");
				String value = node.getText().trim();
				//判斷name值
				if("connection.jdbc_driver".equalsIgnoreCase(name)){
					cfg.setDriver(value);
				}else if("connection.url".equalsIgnoreCase(name)){
					cfg.setUrl(value);
				}else if("connection.username".equalsIgnoreCase(name)){
					cfg.setUsername(value);
				}else if("connection.password".equalsIgnoreCase(name)){
					cfg.setPassword(value);
				}
			}
			//獲取全部mapping節點
			nodes = document.selectNodes("hibernate-configuration/session-factory/mapping");
			//用一個list集合去放mapping
			List<String> mappings = new ArrayList<String>();
			for (Node n : nodes) {
				String m = n.valueOf("@resource");
				mappings.add(m);
			}
			cfg.setMappings(mappings);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		new HibernateConfiguration();
	}
}
1. 下面解析Student.hbm.xml建立表
    - 首先,咱們建立兩個類Table,Column用於存放表和列
public class Table {
	private String tablename;
	private List<Column> columns;
	public String getTablename() {
		return tablename;
	}
	public void setTablename(String tablename) {
		this.tablename = tablename;
	}
	public List<Column> getColumns() {
		return columns;
	}
	public void setColumns(List<Column> columns) {
		this.columns = columns;
	}
}
public class Column {
	private boolean isPK;  //當前列是否爲主鍵
	private String columnName;  //列名稱
	private String columnType;  //列類型
	private String columnLength; //列長度
	public boolean isPK() {
		return isPK;
	}
	public void setPK(boolean isPK) {
		this.isPK = isPK;
	}
	public String getColumnName() {
		return columnName;
	}
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}
	public String getColumnType() {
		return columnType;
	}
	public void setColumnType(String columnType) {
		this.columnType = columnType;
	}
	public String getColumnLength() {
		return columnLength;
	}
	public void setColumnLength(String columnLength) {
		this.columnLength = columnLength;
	}	
}

具體的解析過程數據庫

public class HibernateConfiguration {
	private Config cfg;
	//指定默認文件的構造器
	public HibernateConfiguration(){
		this("src/hibernate.cfg.xml");
	}
	//指定本身定義文件名字的構造器
	public HibernateConfiguration(String file){
		 init(file);
		 System.out.println(cfg);
	}
	public void init(String file){
		cfg = new Config();
		//獲取解析器
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File(file));
			//獲取全部的property節點
			List<Node> nodes = document.selectNodes("hibernate-configuration/session-factory/property");
			for (Node node : nodes) {
				String name = node.valueOf("@name");
				String value = node.getText().trim();
				//判斷name值
				if("connection.jdbc_driver".equalsIgnoreCase(name)){
					cfg.setDriver(value);
				}else if("connection.url".equalsIgnoreCase(name)){
					cfg.setUrl(value);
				}else if("connection.username".equalsIgnoreCase(name)){
					cfg.setUsername(value);
				}else if("connection.password".equalsIgnoreCase(name)){
					cfg.setPassword(value);
				}
			}
			//獲取全部mapping節點
			nodes = document.selectNodes("hibernate-configuration/session-factory/mapping");
			//用一個list集合去放mapping
			List<String> mappings = new ArrayList<String>();
			for (Node n : nodes) {
				String m = n.valueOf("@resource");
				mappings.add(m);
			}
			cfg.setMappings(mappings);
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 獲取鏈接
	 * @return
	 */
	public Connection getConn(){
		Connection conn = null;
		try {
			Class.forName(cfg.getDriver());
			DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	/**
	 * 解析xml中的mapping標籤
	 * @param mapping
	 * @return
	 */
	public String getSql(String mapping){
		StringBuilder builder = new StringBuilder();
		String sqls = "";
		//拼接鍵表語句
		builder.append("create table ");
		//對xml文件進行解析
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(new File("src/"+mapping));
			Table table = getTable(document);
			//添加表名
			builder.append(table.getTablename()+"(");
			//得到全部列
			List<Column> list = table.getColumns();
			for (Column column : list) {
				//判斷是不是主鍵列
				if(column.isPK()){
					builder.append(column.getColumnName()+" "+column.getColumnType()+"("+column.getColumnLength()+") primary key,");
				}else{
					//判斷列是否有長度
					if(column.getColumnLength() == null){
						builder.append(column.getColumnName()+" "+column.getColumnType()+",");
					}else{
						builder.append(column.getColumnName()+" "+column.getColumnType()+"("+column.getColumnLength()+"),");
					}
				}
			}
			sqls =  builder.substring(0, builder.length()-1);
			sqls += ")";
		} catch (DocumentException e) {
		}
		return sqls;
	}
	/**
	 * 根據document來獲取Table對象
	 */
	 public Table getTable(Document document){
		 Table table = new Table();
		 //定義列的集合
		 List<Column> columns = new ArrayList<Column>();
		 //取class節點
		 Node node_class = document.selectSingleNode("hibernate-mapping/class");
		 String tbname = node_class.valueOf("@table");
		 //判斷文檔指定標籤中是否存在table屬性,若不存在,則以name屬性值做爲表名稱
		 tbname = tbname.equals("")?node_class.valueOf("@name"):tbname;
		 table.setTablename(tbname);
		 Node node_id = node_class.selectSingleNode("id");
		 Column c = new Column();
		 c.setPK(true);
		 //判斷有沒有column屬性,沒有就則以name屬性值做爲列名稱
		 c.setColumnName(node_id.valueOf("@column").equals("")?node_id.valueOf("@name"):node_id.valueOf("@column"));
		 //判斷有沒長度屬性,沒有則設置爲空
		 c.setColumnLength(node_id.valueOf("@length").equals("")?null:node_id.valueOf("@length"));
		 //取type
		 c.setColumnType(node_id.valueOf("@type"));
		 //將主鍵列加到集合中
		 columns.add(c);
		 //搜索class下的property節點
		 List<Node> nodes = node_class.selectNodes("property");
		 for (Node node : nodes) {
			 c = new Column();
			 //判斷有沒有column屬性,沒有就則以name屬性值做爲列名稱
			 c.setColumnName(node.valueOf("@column").equals("")?node.valueOf("@name"):node.valueOf("@column"));
			 //判斷有沒長度屬性,沒有則設置爲空
			 c.setColumnLength(node.valueOf("@length").equals("")?null:node.valueOf("@length"));
			 //取type
			 c.setColumnType(node.valueOf("@type"));
			 //將列加到集合中
			 columns.add(c);
		}
		table.setColumns(columns);
		return table;
	 }
	/**
	 * 獲取全部的SQL語句,由於在xml中可能不僅有一個mapping標籤
	 * @return
	 */
	public List<String> getSqls(){
		List<String> sqls = new ArrayList();
		//從Config對象mappings中取出一個xml文件路徑
		for (String file : cfg.getMappings()) {
			String sql = getSql(file);
			sqls.add(sql);
		}
		return sqls;
	}
	/**
	 * 建立表
	 * @param args
	 */
	public void createTable(){
		//獲取鏈接
		Connection conn = getConn();
		//獲取建立表所須要的sqls
		List<String> sqls = getSqls();
		Statement stat = null;
		//循環取出
		try {
			for (String sql : sqls) {
				//建立一個類型聲明對象
				stat = conn.createStatement();
				//執行sql
				stat.execute(sql);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			//關閉鏈接
			try {
				if(stat != null){
					stat.close();
					stat = null;
				}
				if(conn != null){
					conn.close();
					conn = null;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}	
	}	
	public static void main(String[] args) {
		HibernateConfiguration hcfg = new HibernateConfiguration();
		hcfg.createTable();
	}
}
相關文章
相關標籤/搜索