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

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

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

    隨筆 - 3, 文章 - 152, 評論 - 17, 引用 - 0
    數(shù)據(jù)加載中……

    SAX之Java實(shí)現(xiàn)學(xué)習(xí)筆記

    本文假設(shè)讀者對XML有些了解

     

    首先,先給出一個比較基本的處理xml文件的程序。你不必細(xì)看,直接跳過即可。需要時可以返回來看。

     

     

    Echo01.java

     

    import java.io.*;

     

    import org.xml.sax.*;

    import org.xml.sax.helpers.DefaultHandler;

     

    import javax.xml.parsers.SAXParserFactory;

    import javax.xml.parsers.ParserConfigurationException;

    import javax.xml.parsers.SAXParser;

     

    public class Echo01 extends DefaultHandler

    {

        StringBuffer textBuffer;

     

        public static void main(String argv[])

        {

            if (argv.length != 1) {

                System.err.println("Usage: cmd filename");

                System.exit(1);

            }

     

            // Use an instance of ourselves as the SAX event handler

            DefaultHandler handler = new Echo01();

     

            // Use the default (non-validating) parser

                  SAXParserFactory factory = SAXParserFactory.newInstance();

            try {

                // Set up output stream

                out = new OutputStreamWriter(System.out, "UTF-8");

     

                // Parse the input

                SAXParser saxParser = factory.newSAXParser();

                saxParser.parse( new File(argv[0]), handler);

     

            } catch (Throwable t) {

                t.printStackTrace();

            }

            System.exit(0);

        }

     

        static private Writer  out;

     

        //===========================================================

        // SAX DocumentHandler methods

        //===========================================================

     

        public void startDocument()

        throws SAXException

        {

            emit("<?xml version='1.0' encoding='UTF-8'?>");

            nl();

        }

     

        public void endDocument()

        throws SAXException

        {

            try {

                nl();

                out.flush();

            } catch (IOException e) {

                throw new SAXException("I/O error", e);

            }

        }

     

        public void startElement(String namespaceURI,

                                 String sName, // simple name

                                 String qName, // qualified name

                                 Attributes attrs)

        throws SAXException

        {

            echoText();

                  String eName = sName; // element name

            if ("".equals(eName)) eName = qName; // not namespaceAware

            emit("<"+eName);

            if (attrs != null) {

                for (int i = 0; i < attrs.getLength(); i++) {

                    String aName = attrs.getLocalName(i); // Attr name

                    if ("".equals(aName)) aName = attrs.getQName(i);

                    emit(" ");

                    emit(aName+"=\""+attrs.getValue(i)+"\"");

                              }

            }

            emit(">");

        }

     

        public void endElement(String namespaceURI,

                               String sName, // simple name

                               String qName  // qualified name

                              )

        throws SAXException

        {

            echoText();

            String eName = sName; // element name

            if ("".equals(eName)) eName = qName; // not namespaceAware

            emit("</"+eName+">");

        }

     

        public void characters(char buf[], int offset, int len)

        throws SAXException

        {

                         String s = new String(buf, offset, len);

            if (textBuffer == null) {

               textBuffer = new StringBuffer(s);

            } else {

               textBuffer.append(s);

            }

        }

     

        //===========================================================

        // Utility Methods ...

        //===========================================================

     

        // Display text accumulated in the character buffer

        private void echoText()

        throws SAXException

        {

            if (textBuffer == null) return;

                               String s = ""+textBuffer;

                  emit(s);

                  textBuffer = null;

        }

     

        // Wrap I/O exceptions in SAX exceptions, to

        // suit handler signature requirements

        private void emit(String s)

        throws SAXException

        {

            try {

                out.write(s);

                out.flush();

            } catch (IOException e) {

                throw new SAXException("I/O error", e);

            }

        }

     

        // Start a new line

        private void nl()

        throws SAXException

        {

          String lineEnd =  System.getProperty("line.separator");

            try {

                out.write(lineEnd);

            } catch (IOException e) {

                throw new SAXException("I/O error", e);

            }

        }

    }

     

    從程序中可以看出,解析一個XML文件的核心語句是下面一部分:

         // Use an instance of ourselves as the SAX event handler

            DefaultHandler handler = new Echo01();

     

            // Use the default (non-validating) parser

                  SAXParserFactory factory = SAXParserFactory.newInstance();

            try {

                // Set up output stream

                out = new OutputStreamWriter(System.out, "UTF-8");

     

                // Parse the input

                SAXParser saxParser = factory.newSAXParser();

                saxParser.parse( new File(argv[0]), handler);

     

            } catch (Throwable t) {

                t.printStackTrace();

            }

    先是創(chuàng)建一個SAXParserFactory工廠類的實(shí)例,然后通過SAXParser saxParser = factory.newSAXParser(); 這個工廠類的方法創(chuàng)建了一個saxParser。將xml文件(new File(argv[0]))和一個Sax Event Handlerhandler)(在這個程序里面,這個Handler其實(shí)是本身這個類,這個類繼承了org.xml.sax.helpers.DefaultHandler 這個類,并且在前面初始化了它:DefaultHandler handler = new Echo01();  )傳遞給它,讓它進(jìn)行解析。

     

    關(guān)于xml文件的解析過程中的處理全部在Handler里面實(shí)現(xiàn)。一般Parser接受的是DefaultHandler或者HandlerBase這兩個類。 這個例子里面的類是繼承DefaultHandler這個虛類的。看下圖:

     

     

    DefaultHandler是實(shí)現(xiàn)了EntityResolver, DTDHandler, ContentHandler, ErrorHandler四個接口的虛類。分別定義了如下的方法:

     

     

    不同的方法,在不同的時候被Parser調(diào)用,(這個不同的時候就是Event-based

    詳細(xì)介紹:(暫略)

     

     

    DefualtHandlerUML圖如下:

     

     

    看完Handler,再轉(zhuǎn)過頭去看Parser,在代碼里面用的是SAXParser(SAXParser saxParser)

    仔細(xì)看里面的代碼

     

    你會發(fā)現(xiàn),其實(shí)它并沒有自己完成解析的工作,而是Wrap了另二個類XMLReaderParser來完成解析工作。原來SAXParser只是起到一個Adapter的工作而已。

     

    UML:

     

    那我們?nèi)タ纯?/SPAN>Parserorg.xml.sax.Parser)去,

     

    看到Parser的代碼,你會大失所望。原來Parser也只是一個空殼子而已

     

     

    圖中你可以看到經(jīng)過層層查找的Parser只是一個接口而已。

     

    回想一下前面看到生成解析器代碼的時候

    使用了工廠模式

                  SAXParserFactory factory = SAXParserFactory.newInstance();

            try {

                // Set up output stream

                out = new OutputStreamWriter(System.out, "UTF-8");

     

                // Parse the input

                SAXParser saxParser = factory.newSAXParser();

                saxParser.parse( new File(argv[0]), handler);

    完全由SAXParserFactory 這個類來控制產(chǎn)生的Parser的類型。我們只是拿來用就可以了。秘密一定藏在里面。

     

    看到代碼,發(fā)現(xiàn)原來這個工廠自己也是一個虛類,連返回的工廠的實(shí)例都是該虛工廠的一個實(shí)現(xiàn)而已。

    再去看真正的實(shí)現(xiàn)org.apache.crimson.jaxp.SAXParserFactoryImpl

     

     

    發(fā)現(xiàn)它又wrapSAXParserImpl,可知SAXParserImplSAXParser的一個子類。

    繼續(xù)追蹤下去,因?yàn)?/SPAN>SAXParserImpl繼承了SAXParser,所以它也繼承了SAXParser的方法。在SAXParserImpl體內(nèi),并沒有發(fā)現(xiàn)覆寫掉parser方法的地方,所以SAXParserImplparser也就是SAXParser的那個parser,呵呵,是不是有點(diǎn)繞口令的味道?那么怎么我們繞了半天,又回去了呢。再仔細(xì)看看SAXParserparser方法

     

     

     

    可以看到其實(shí)在里面的Parser parser這個實(shí)例是調(diào)用了this.getParser()這個方法來得到的。再看看SAXParser里面的getParser方法

     

     

    是不是有點(diǎn)感覺了? 對了,其實(shí)這個方法就是留給繼承了SAXParserSAXParserImpl來實(shí)現(xiàn)的,這樣,SAXParser的子類就可以自由的改換Parser。只要改寫掉getParser方法就可以了。

    急忙去看SAXParserImplgetParser這個方法

     

     

     

    你會發(fā)現(xiàn)你又上當(dāng)了,這里又給出了很曖昧的代碼,并不是我們所猜想的那樣是一個真正的實(shí)現(xiàn),再仔細(xì)看看。 注釋里面有這么句話:Adapt a SAX2 XMLReader into a SAX1 Parser

    XMLReader,是不是很熟?想想看哪里看到過的?對了,剛剛在SAXParser體內(nèi)Wrap的二個類,一個是我們追蹤至今的Parser,另一個就是XMLReader,原來這個XMLReader才是才是現(xiàn)在在用的SAX2解析器,而為了保持對以前系統(tǒng)的兼容才保留了SAX1解析器Parser,但其實(shí)是通過對XMLReaderWrap得到的。只是個Adapte而已。

     

    好了,現(xiàn)在可以集中火力去查找XMLReader了。有了剛剛的經(jīng)驗(yàn),很容易的,我們發(fā)現(xiàn),和Parser一樣,XMLReader也是一個接口:

     

     

    很容易的,我們找到XMLReaderImpl

     

     

     

    和里面的parse方法:

     

     

     

    可以看到里面選擇parse的部分,是根據(jù)是否需要Validation選擇不同的parser的實(shí)現(xiàn)。

     

     

    Parser的真面目已經(jīng)找到啦。

    Parser2

     

     

    ValidatingParser

     

    其實(shí),ValidatingParser也是繼承了Parser2的一個類而已,再加上了驗(yàn)證合法性的功能。

     

     

    今天先找到這里吧。 SAX的實(shí)現(xiàn)包含了許多Pattern,這里只是冰山一角,慢慢回味。。。

    posted on 2005-03-28 16:15 閱讀(452) 評論(0)  編輯  收藏 所屬分類: Java_Xml

    主站蜘蛛池模板: 亚洲成人高清在线观看| 伊人久久大香线蕉亚洲五月天| 亚洲五月丁香综合视频| 色偷偷亚洲女人天堂观看欧| 亚洲精品女同中文字幕| 精品亚洲aⅴ在线观看| 亚洲国产精品专区| 亚洲AV无码精品色午夜果冻不卡| 日本高清免费网站| 成年网站免费视频A在线双飞| 日本视频在线观看永久免费| 成人浮力影院免费看| 无码免费一区二区三区免费播放 | 国产一精品一AV一免费| 最近2018中文字幕免费视频| 天天摸夜夜摸成人免费视频 | 免费无码肉片在线观看| 麻豆视频免费播放| 色欲A∨无码蜜臀AV免费播| aa级一级天堂片免费观看| 又粗又硬又黄又爽的免费视频| 亚洲精品tv久久久久久久久| 青青草原亚洲视频| 亚洲无成人网77777| 国产精品亚洲五月天高清| 色www免费视频| 日韩免费人妻AV无码专区蜜桃| 国产精品白浆在线观看免费 | 69天堂人成无码麻豆免费视频| 亚洲国产一区视频| 亚洲国产成人久久综合一区77| 亚洲乱码日产精品a级毛片久久| 亚洲AV无码不卡在线播放| 亚洲AV无码一区二区三区电影 | 1000部禁片黄的免费看 | 国产成人精品免费午夜app| 免费大片黄手机在线观看| 日韩精品一区二区亚洲AV观看| 黄人成a动漫片免费网站| 午夜性色一区二区三区免费不卡视频 | 免费精品久久久久久中文字幕|