XML(可擴展標記語言)

                                                                                        XML(可擴展標記語言)
一 ,解析XML的兩種方式:SAX(sample api for xml)和dom(文檔對象模型)例如:jdom和dom4j解析XML文件
XML文檔的解析方式:
DOM
DOM解析器使用樹形模型,把XML文檔轉化爲一個包含其內容的樹,並可以對樹進行遍歷。
SAX
SAX解析器採用了基於事件的模型,解析XML文檔的時候可以觸發一系列的事件。
JDOM
JDOM的目的是成爲Java特定文檔模型,它簡化與XML的交互並且比使用DOM實現更快。 
DOM4J
DOM4J是一個非常非常優秀的Java XML API,具有性能優異、功能強大和極端易用使用的特點。 

區別與聯繫:
1.SAX 這種處理的優點非常類似於流媒體的優點。分析能夠立即開始,而不是等待所有的數據被處理。而且,由於應用程序只是在讀取數據時檢查數據,
因此不需要將數據存儲在內存中。這對於大型文檔來說是個巨大的優點。事實上,應用程序甚至不必解析整個文檔;它可以在某個條件得到滿足時停止解析。
一般來說,SAX 還比它的替代者 DOM 快許多。

2.選擇 DOM 還是選擇 SAX ? 對於需要自己編寫代碼來處理 XML 文檔的開發人員來說,選擇 DOM 還是 SAX 解析模型是一個非常重要的設計決策。
 DOM 採用建立樹形結構的方式訪問 XML 文檔,而 SAX 採用的事件模型。 DOM 解析器把 XML 文檔轉化爲一個包含其內容的樹,並可以對樹進行遍歷。
用 DOM 解析模型的優點是編程容易,開發人員只需要調用建樹的指令,然後利用navigation APIs訪問所需的樹節點來完成任務。可以很容易的添加和修改樹中的元素。
然而由於使用 DOM 解析器的時候需要處理整個 XML 文檔,所以對性能和內存的要求比較高,尤其是遇到很大的 XML 文件的時候。由於它的遍歷能力,DOM 解析器常用於 XML 文檔需要頻繁的改變的服務中。 SAX 解析器採用了基於事件的模型,它在解析 XML 文檔的時候可以觸發一系列的事件,當發現給定的tag的時候,它可以激活一個回調方法,告訴該方法制定的標籤已經找到。SAX 對內存的要求通常會比較低,因爲它讓開發人員自己來決定所要處理的tag.特別是當開發人員只需要處理文檔中所包含的部分數據時,SAX 這種擴展能力得到了更好的體現。但用 SAX 解析器的時候編碼工作會比較困難,而且很難同時訪問同一個文檔中的多處不同數據。 

二,在XML初始化數據導入到數據庫中(dom4j)
(1)配置
init.xml
<?xml version="1.0" encoding="UTF-8"?>
<inits package="cn.com.leadfar.oa.model">
<entity class="Company" 
name="北京領航致遠科技有限公司" 
description="北京領航致遠科技有限公司"
call="partyService.addParty"
>
<entity class="Department" name="技術部">
<entity class="Position" name="高級工程師">
<entity class="Person" name="張三" sex="男">
</entity>
<entity class="Person" name="李四" sex="女">
</entity>
</entity>
</entity>
<entity class="Department" name="財務部">
</entity>
<entity class="Department" name="培訓中心">
<entity class="Position" name="資深講師">
<entity class="Person" name="王五">
</entity>
</entity>
</entity>
<entity class="Department" name="總裁辦">
</entity>
</entity>
</inits>

(2)配置applicationContext-service.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

<bean id="initService" class="cn.com.leadfar.oa.service.impl.InitServiceImpl">
<property name="path" value="init.xml"/>
</bean>
</beans>


(3)讀取配置的XML文件
XPath 是在 XML 文檔中查找信息的語言 
XPath 是通過元素和屬性進行查找
XPath簡化了Dom4j查找節點的過程
使用XPath必須導入jaxen-1.1-beta-7.jar

package cn.com.leadfar.oa.service.impl;

import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import cn.com.leadfar.oa.service.InitService;

public class InitServiceImpl implements InitService,BeanFactoryAware {

private String path;
private BeanFactory factory;
/**
 * Spring在實例化InitServiceImpl對象的時候,如果InitServiceImpl類實現了
 * BeanFactoryAware接口,Spring會自動把自身(BeanFactory)注入到此對象
 */
@Override
public void setBeanFactory(BeanFactory factory) throws BeansException {
this.factory = factory;
}

@Override
public void addInitDatas() {
try {
//從類路徑的根目錄中讀取指定的包含初始化數據的XML文件
Document document = new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(path));
//document.selectNodes("//entity");
//文檔根元素
Element root = document.getRootElement();
//從文檔根元素中提取出實體類所在的包名
String pkg = root.attributeValue("package");
//得到根元素下面包含的所有的entity元素
List entityElements = root.elements("entity");
for (Iterator iterator = entityElements.iterator(); iterator
.hasNext();) {
Element entityElement = (Element) iterator.next();
addEntity(pkg,entityElement,null,null);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
private void addEntity(String pkg,Element entityElement,Object parentEntity,String callString){
try {
//根據包名和類名,得到全路徑類名
String clz = pkg + "." +entityElement.attributeValue("class");
//根據全路徑類名,創建實體對象
Object entity = Class.forName(clz).newInstance();
//給entity對象賦值
//即提取出當前Element中的所有屬性,並用反射機制給entity對象賦值
Iterator iterator = entityElement.attributeIterator();
while(iterator.hasNext()){
Attribute attribute = (Attribute)iterator.next();
String propertyName = attribute.getName();
if(!propertyName.equals("class") && !propertyName.equals("call")){
String propertyValue = attribute.getValue();
//給entity相應的屬性賦值,這裏使用的是apache-commons-beanutils工具包,所以需要加入這個依賴包
BeanUtils.copyProperty(entity, propertyName, propertyValue);
}
}
//判斷parentEntity是否爲空,如果不是空,則給parent對象賦值
//BeanUtils.copyProperty(entity, "parent", parentEntity);
if(parentEntity != null){
Method[] ms = entity.getClass().getMethods();
for(Method m:ms){
if(m.getName().equals("setParent")){
m.invoke(entity, parentEntity);
}
}
}
//要調用哪個服務對象的哪個方法
String call = entityElement.attributeValue("call");
if(call != null){
callString = call;
}
if(callString == null){
throw new RuntimeException("沒有找到call屬性,無法獲知要調用哪個服務對象的哪個方法!請配置call屬性!");
}
//得到服務對象的ID
String serviceId = callString.substring(0, callString.indexOf("."));
//得到要調用的方法名稱
String methodName = callString.substring(callString.indexOf(".")+1);
//通過BeanFactory得到服務對象
Object service = factory.getBean(serviceId);
//得到service對象的所有方法
Method[] ms = service.getClass().getMethods();
for(Method m:ms){
if(m.getName().equals(methodName)){
//調用其中我們想要調用的方法
m.invoke(service, entity);
}
}
//判斷當前entity下面是否還有其他的entity元素
List subEntityElements = entityElement.elements("entity");
for (Iterator iterator2 = subEntityElements.iterator(); iterator2
.hasNext();) {
Element e = (Element) iterator2.next();
//遞歸插入本entity元素下面的其它entity對象
addEntity(pkg,e,entity,callString);
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}

public void setPath(String path) {
this.path = path;
}

}

(4)測試用例
package cn.com.leadfar.oa.service;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import junit.framework.TestCase;

public class InitServiceTest extends TestCase {

public void testAddInitDatas() {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-*.xml");
InitService is = (InitService)factory.getBean("initService");
is.addInitDatas();
}

}

此時數據庫中就擁有導入的數據了



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章