<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    jinfeng_wang

    G-G-S,D-D-U!

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

    http://hi.baidu.com/python811022/blog/item/5ed31dcee519243ab700c86c.html


    Digester框架屬于Jakarta Commons,它以規則和模式為基礎處理XML文檔。與SAX和DOM之類的標準API相比,Digester不涉及太多的細節問題,非常適合于對XML文檔進行簡單的處理。

    在Java和XML開發中,一個常見的任務是把XML文檔轉換成對應的Java Bean對象的層次結構。人們經常用標準的SAX和DOM API來完成這個任務。雖然這兩種API都很強大和靈活,但對于某些簡單的任務來說,它們顯得操作層次太低,也就是說,涉及了太多的細節問題。Jakarta Digester框架能夠很好地滿足這類場合的需要。

    Digester框架簡介

    Jakarta的Digester框架從Struts框架發展而來,原先被用來處理struts-config.xml配置文件,但很快人們認識到它有著更廣泛的用途,把它轉入了Jakarta Commons項目。Jakarta Commons的目標是提供一個“可重用Java組件的倉庫”。Digester最新的版本是1.3,于2002年8月13日發布。

    Digester框架允許開發者指定一組動作,當解析器在XML文檔中發現某些特定的簡單模式時動作被執行。Digester框架帶有10個預定義的規則(Rule),涵蓋了unmarshalling XML(例如創建Bean或設置Bean屬性)的大多數需求( marshalling的原意是指“配制整齊,編組列車”,marshalling是在內存中為Java對象生成XML描述文檔的過程,而unmarshalling是指把XML形式的描述轉換到可用Java代碼操作的對象的過程,我們稱之為“反配制”),但必要時用戶可以定義和實現自己的規則。

    在本文的例子中,我們將反配制下面這個XML文檔:

    <?xml version="1.0"?>
    <catalog library="somewhere">
    <book>
    <author>Author 1</author>
    <title>Title 1</title>
    </book>
    <book>
    <author>Author 2</author>
    <title>His One Book</title>
    </book>
    <magazine>
    <name>Mag Title 1</name>
    <article page="5">
    <headline>Some Headline</headline>
    </article>
    <article page="9">
    <headline>Another Headline</headline>
    </article>
    </magazine>
    <book>
    <author>Author 2</author>
    <title>His Other Book</title>
    </book>
    <magazine>
    <name>Mag Title 2</name>
    <article page="17">
    <headline>Second Headline</headline>
    </article>
    </magazine>
    </catalog>

    下面是Bean的代碼。注意使用Digester框架時,Bean類必須定義成public。

    import java.util.Vector;
    public class Catalog {
    private Vector books;
    private Vector magazines;
    public Catalog() {
    books = new Vector();
    magazines = new Vector();
    }
    public void addBook( Book rhs ) {
    books.addElement( rhs );
    }
    public void addMagazine( Magazine rhs ) {
    magazines.addElement( rhs );
    }
    public String toString() {
    String newline = System.getProperty( "line.separator" );
    StringBuffer buf = new StringBuffer();
    buf.append( "--- Books ---" ).append( newline );
    for( int i=0; i<books.size(); i++ ){
    buf.append( books.elementAt(i) ).append( newline );
    }
    buf.append( "--- Magazines ---" ).append( newline );
    for( int i=0; i<magazines.size(); i++ ){
    buf.append( magazines.elementAt(i) ).append( newline );
    }
    return buf.toString();
    }
    }
    //===================================================
    public class Book {
    private String author;
    private String title;
    public Book() {}
    public void setAuthor( String rhs ) { author = rhs; }
    public void setTitle( String rhs ) { title = rhs; }
    public String toString() {
    return "Book: Author='" + author + "' Title='" + title + "'";
    }
    }
    //===================================================
    import java.util.Vector;
    public class Magazine {
    private String name;
    private Vector articles;
    public Magazine() {
    articles = new Vector();
    }
    public void setName( String rhs ) { name = rhs; }
    public void addArticle( Article a ) {
    articles.addElement( a );
    }
    public String toString() {
    StringBuffer buf = new StringBuffer( "Magazine: Name='" + name + "' ");
    for( int i=0; i<articles.size(); i++ ){
    buf.append( articles.elementAt(i).toString() );
    }
    return buf.toString();
    }
    }
    //===================================================
    public class Article {
    private String headline;
    private String page;
    public Article() {}
    public void setHeadline( String rhs ) { headline = rhs; }
    public void setPage( String rhs ) { page = rhs; }
    public String toString() {
    return "Article: Headline='" + headline + "' on page='" + page + "' ";
    }
    }



    指定模式和規則

    Digester框架以模式(Pattern)和規則(Rule)為基礎處理輸入的XML。模式必須與XML元素匹配,包括其名字和在文檔樹內的位置。描述匹配模式的語法類似于XPath匹配模式,例如:catalog模式匹配頂層的<catalog>元素,catalog/book模式匹配直接嵌套在<catalog>元素內的<book>元素(但不匹配文檔內其他位置的<book>元素)。

    所有的模式都必須指定其完整名稱——從根元素開始的完整路徑。唯一的例外是包含通配符(“*”)的模式,例如*/name模式匹配XML文檔內任何位置的<name>元素。但是根元素不必特別指出,因為所有的路徑都是從根元素開始的絕對路徑。

    當Digester發現一個指定的模式,它就執行關聯的任務。由此可見,Digester框架顯然與SAX解析器有著密切的關系(實際上,Digester類實現了org.xml.sax.ContentHandler,并維護著解析棧)。所有在Digester中使用的規則必須擴展org.apache.commons.digester.Rule,后者本身提供了一些類似于SAX的ContentHandler回調函數的方法。例如,當遇到匹配元素的開始標記和結束標記時,begin()方法和end()方法將分別被調用。

    一旦遇到匹配元素的內容,body()方法被調用;最后被調用的方法是finish(),這個方法在匹配元素的結束標記處理完畢之后被調用,用來執行可能需要的事后清理任務。然而,大多數時候我們不必關注這些方法,因為框架提供的標準規則很可能已經提供了所有必需的功能。

    要反配制一個文檔,首先創建一個org.apache.commons.digester.Digester類的實例,如果必要的話,進行一些配置操作,指定必需的模式和規則,最后向parse()方法傳遞一個XML文件的引用。下面的DigesterDriver示范了這一處理過程(必須在命令行上指定輸入XML文檔的名稱)。

    import org.apache.commons.digester.*;
    import java.io.*;
    import java.util.*;
    public class DigesterDriver {
    public static void main( String[] args ) {
    try {
    Digester digester = new Digester();
    digester.setValidating( false );
    digester.addObjectCreate( "catalog", Catalog.class );
    digester.addObjectCreate( "catalog/book", Book.class );
    digester.addBeanPropertySetter( "catalog/book/author", "author" );
    digester.addBeanPropertySetter( "catalog/book/title", "title" );
    digester.addSetNext( "catalog/book", "addBook" );
    digester.addObjectCreate( "catalog/magazine", Magazine.class );
    digester.addBeanPropertySetter( "catalog/magazine/name", "name" );
    digester.addObjectCreate( "catalog/magazine/article", Article.class );
    digester.addSetProperties( "catalog/magazine/article", "page", "page" );
    digester.addBeanPropertySetter( "catalog/magazine/article/headline" );
    digester.addSetNext( "catalog/magazine/article", "addArticle" );
    digester.addSetNext( "catalog/magazine", "addMagazine" );
    File input = new File( args[0] );
    Catalog c = (Catalog)digester.parse( input );
    System.out.println( c.toString() );
    } catch( Exception exc ) {
    exc.printStackTrace();
    }
    }
    }

    在上面的代碼中,我們首先創建了Digester類的一個實例digester,然后指定它不要用DTD驗證XML文檔的合法性——這是因為我們沒有為XML文檔定義DTD。接下來,我們指定了模式和關聯的規則:ObjectCreateRule創建指定類的一個實例,并將它壓入解析棧。SetPropertiesRule把Bean屬性設置成當前XML元素的屬性值——規則的第一個參數是XML屬性的名稱,第二個參數是Bean屬性的名稱。

    SetPropertiesRule獲取的是XML屬性的值,而BeanPropertySetterRule獲取的是位于當前元素內的原始字符數據值。使用BeanPropertySetterRule時不必指定要設置的Bean屬性名字,默認是當前XML元素的名稱。在上面的例子中,在匹配catalog/magazine/article/headline模式的規則定義中使用的就是默認值。最后,SetNextRule彈出解析棧頂部的對象,并把該對象傳遞給它下面對象的指定名稱的方法——通常用來把一個配置完畢的Bean插入父對象。

    注意,我們可以為同一個模式注冊多個規則。如果注冊了多個規則,則這些規則按照它們被加入到Digester的次序執行,例如,如果要處理catalog/magazine/article的

    元素,我們首先創建合適的article Bean,然后設置page屬性,最后彈出完成后的article Bean,并把它插入magazine。

    調用任意方法

    我們不僅可以設置Bean的屬性,而且還可以調用堆棧內對象的任意方法。這通過CallMethodRule完成,我們只需指定方法名字,如有必要,再說明調用的參數類型和數量。CallParamRule用來定義傳遞給被調用函數的參數值,參數值可以從當前XML元素的命名的屬性獲取,也可以從當前元素包含的原始字符數據獲取。例如,在前面實現DigesterDriver的例子中,我們可以不用BeanPropertySetterRule,而是通過顯式調用屬性的set方法達到同樣的目的:

    digester.addCallMethod( "catalog/book/author", "setAuthor", 1 );
    digester.addCallParam( "catalog/book/author", 0 );

    上面的第一行代碼給出了要調用的方法(即setAuthor()),以及該調用需要的參數數量(即1)。第二行代碼的意思是從元素包含的字符數據獲取函數參數的值,把它作為參數數組的第一個傳入(即索引是0的數組元素)。如果我們指定了XML元素屬性的名稱(例如digester.addCallParam( "catalog/book/author", 0, "author" );),則參數值將從當前元素的相應屬性值獲取。

    這里必須注意的是,“digester.addCallMethod( "pattern", "methodName", 0 );”這個語句不是指定了一個不帶參數的方法調用,而是指定了帶有一個參數的方法調用,它的值就是當前XML元素的字符數據!這樣,我們又有了另一種替代BeanPropertySetterRule的辦法:

    digester.addCallMethod( "catalog/book/author", "setAuthor", 0 );

    如果要調用一個確實沒有參數的方法,必須采用如下形式:digester.addCallMethod( "pattern", "methodName" );。

    標準規則概要

    下面簡要說明所有標準規則。

    創建

    ObjectCreateRule:利用指定類的默認構造函數,創建該類的一個對象,并把對象壓入棧。當元素處理結束時,對象被彈出。被實例化的類可通過class對象或類的全稱給出。

    FactoryCreateRule:利用指定的工廠類創建一個對象,把對象壓入棧。對于沒有提供默認構造函數的類,這一規則很有用。用于該規則的工廠類必須實現org.apache.commons.digester.ObjectCreationFactory接口。

    設置屬性

    SetPropertiesRule:利用指定名稱的XML元素屬性值,設置頂層Bean的一個或者多個指定名稱的屬性。XML元素的屬性名稱和Bean的屬性名稱以String[]數組形式傳入該規則(通常用來處理

    之類的結構)。

    BeanPropertySetterRule:把頂層Bean的指定名稱的屬性設置成當前XML元素包含的字符數據。(通常用來處理<page>10</page>之類的結構)。

    SetPropertyRule:設置頂層Bean的一個屬性。無論是Bean屬性的名稱,還是賦予該屬性的值,都在當前XML元素中以屬性的形式指定,例如:<article key="page" value="10" />。

    管理父/子關系

    SetNextRule:彈出棧頂的對象,把它傳遞給緊接其下的另一個對象的指定名稱的方法。通常用來把一個已經初始化的Bean插入到父對象。

    SetTopRule:把棧里面上數第二的對象傳遞給頂層的對象。當子對象提供了一個setParenet方法時,這一規則很有用。

    SetRootRule:調用棧底對象的一個方法,并把棧頂的對象作為參數傳入。

    調用任意方法

    CallMethodRule:調用頂層Bean的指定名稱的方法。被調用的方法可以有任意多個參數,參數的值通過后繼的CallParamRule給出。

    CallParamRule:表示方法調用的參數。參數的值或者取自指定名稱的XML元素的屬性,或者是當前元素包含的原始字符數據。這個規則要求用一個整數指定它在參數列表中的位置。

    通過XML指定規則

    在前面的內容中,我們用程序代碼的方式指定模式和規則,這些模式和規則都是在編譯的時候就已經確定,雖然從概念上來講比較簡單,但卻不能說盡善盡美:Digester框架的總體目標是在運行時識別和處理各種數據結構,但如果我們用編程的方法指定模式和規則,則所有行為在編譯時已經固定!如果Java源程序中包含了大量固定的字符串,通常意味著程序在執行某些配置操作,這部分操作可以被(或許是應該被)延遲到運行時進行。

    org.apache.commons.digester.xmlrules包解決了這個問題。這個包提供了一個DigesterLoader類,它能夠從XML文檔讀取模式/規則對,返回配置好的Digester對象。用來配置Digester對象的XML文檔必須遵從digester-rules.dtd,這個DTD是xmlrules包的一部分。

    下面就是本文例子的配置文件rules.xml。有幾點必須說明。

    首先,模式可以用兩種方式指定:或者使用<pattern>元素,或者通過代表規則的XML元素的屬性。這兩種辦法可以混合使用,且<pattern>元素是可以嵌套的。其次,<alias>元素和<set-properties-rule>一起使用,用來把XML屬性映射到Bean屬性。最后,就當前發行的Digester軟件包而言,我們不能在配置文件中指定BeanPropertySetterRule,正如前面所介紹的,我們用CallMethodRule來達到同樣的目標。

    <?xml version="1.0"?>
    <digester-rules>
    <object-create-rule pattern="catalog" classname="Catalog" />
    <set-properties-rule pattern="catalog" >
    <alias attr-name="library" prop-name="library" />
    </set-properties-rule>
    <pattern value="catalog/book">
    <object-create-rule classname="Book" />
    <call-method-rule pattern="author" methodname="setAuthor"
    paramcount="0" />
    <call-method-rule pattern="title" methodname="setTitle"
    paramcount="0" />
    <set-next-rule methodname="addBook" />
    </pattern>
    <pattern value="catalog/magazine">
    <object-create-rule classname="Magazine" />
    <call-method-rule pattern="name" methodname="setName" paramcount="0" />
    <pattern value="article">
    <object-create-rule classname="Article" />
    <set-properties-rule>
    <alias attr-name="page" prop-name="page" />
    </set-properties-rule>
    <call-method-rule pattern="headline" methodname="setHeadline"
    paramcount="0" />
    <set-next-rule methodname="addArticle" />
    </pattern>
    <set-next-rule methodname="addMagazine" />
    </pattern>
    </digester-rules>

    現在,所有實際的操作都轉移到了Digester和DigesterLoader類,XmlRulesDriver類就變得相當簡單。運行下面的XmlRulesDriver時,在第一個命令行參數中指定目錄文檔的名字,在第二個參數中指定rules.xml(注意,DigesterLoader不是從File或者org.xml.sax.InputSource讀取rules.xml文件,而是要求指定一個URL,因此,下面代碼中File引用被轉換成了等價的URL)。

    import org.apache.commons.digester.*;
    import org.apache.commons.digester.xmlrules.*;
    import java.io.*;
    import java.util.*;
    public class XmlRulesDriver {
    public static void main( String[] args ) {
    try {
    File input = new File( args[0] );
    File rules = new File( args[1] );
    Digester digester = DigesterLoader.createDigester( rules.toURL() );
    Catalog catalog = (Catalog)digester.parse( input );
    System.out.println( catalog.toString() );
    } catch( Exception exc ) {
    exc.printStackTrace();
    }
    }
    }

    結束語:本文對Jakarta Commons Digester的介紹就到這里結束。當然,還有許多內容這里尚未涉及。其中一個在這里忽略的主題是XML名稱空間:Digester允許把規則定義成只能對某一個名稱空間內定義的元素起作用。

    另外,我們簡單地提及了通過擴展Rule類開發定制規則的問題。按照習慣,Digester類提供了push()、peek()和pop()方法,使得開發者能夠自由地直接操作解析棧。

    參考:

    Jakarta Commons Digester Homepage

    Jakarta Struts Homepage


    posted on 2008-03-10 17:09 jinfeng_wang 閱讀(503) 評論(0)  編輯  收藏 所屬分類: javaZZ
    主站蜘蛛池模板: 亚洲日韩AV一区二区三区四区 | 亚洲人成无码www久久久| 中文字幕在线观看亚洲日韩| 亚洲精品视频免费在线观看| 亚洲成年轻人电影网站www | 69av免费视频| 亚洲人成电影在线观看青青| 香蕉97超级碰碰碰免费公| 亚洲综合丁香婷婷六月香| 午夜免费福利影院| 波多野结衣免费在线| 99亚洲乱人伦aⅴ精品| 性色av无码免费一区二区三区| 亚洲一级黄色大片| 噼里啪啦电影在线观看免费高清 | 亚洲精品无码久久久久APP| 日本特黄a级高清免费大片| 亚洲大尺度无码无码专线一区| 暖暖免费高清日本一区二区三区| 美女被免费网站在线视频免费| 亚洲男人的天堂在线va拉文| 中文字幕无线码中文字幕免费| 亚洲国产一区在线| 午夜视频免费成人| 国产激情久久久久影院老熟女免费| 自拍偷自拍亚洲精品第1页 | 在线免费观看一级毛片| 污污视频网站免费观看| 精品亚洲一区二区| 精品久久久久成人码免费动漫 | 亚洲色一区二区三区四区| vvvv99日韩精品亚洲| 好猛好深好爽好硬免费视频| 亚洲综合综合在线| 国产成人免费a在线视频app| 精品多毛少妇人妻AV免费久久| 亚洲国产综合精品| 亚洲国产婷婷综合在线精品 | 色噜噜的亚洲男人的天堂| 亚洲精品无码AV人在线播放| 天天影院成人免费观看|