標準由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處理的優勢很是相似於流媒體的優勢。分析可以當即開始,而不是等待全部的數據被處理。並且,因爲應用程序只是在讀取數據時檢查數據,所以不須要將數據存儲在內存中,這對於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是一個開源項目(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(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(); } }