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

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

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

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

    SAX之Java實現學習筆記

    本文假設讀者對XML有些了解

     

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

     

     

    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();

            }

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

     

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

     

     

    DefaultHandler是實現了EntityResolver, DTDHandler, ContentHandler, ErrorHandler四個接口的虛類。分別定義了如下的方法:

     

     

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

    詳細介紹:(暫略)

     

     

    DefualtHandlerUML圖如下:

     

     

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

    仔細看里面的代碼

     

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

     

    UML:

     

    那我們去看看Parserorg.xml.sax.Parser)去,

     

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

     

     

    圖中你可以看到經過層層查找的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 這個類來控制產生的Parser的類型。我們只是拿來用就可以了。秘密一定藏在里面。

     

    看到代碼,發現原來這個工廠自己也是一個虛類,連返回的工廠的實例都是該虛工廠的一個實現而已。

    再去看真正的實現org.apache.crimson.jaxp.SAXParserFactoryImpl

     

     

    發現它又wrapSAXParserImpl,可知SAXParserImplSAXParser的一個子類。

    繼續追蹤下去,因為SAXParserImpl繼承了SAXParser,所以它也繼承了SAXParser的方法。在SAXParserImpl體內,并沒有發現覆寫掉parser方法的地方,所以SAXParserImplparser也就是SAXParser的那個parser,呵呵,是不是有點繞口令的味道?那么怎么我們繞了半天,又回去了呢。再仔細看看SAXParserparser方法

     

     

     

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

     

     

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

    急忙去看SAXParserImplgetParser這個方法

     

     

     

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

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

     

    好了,現在可以集中火力去查找XMLReader了。有了剛剛的經驗,很容易的,我們發現,和Parser一樣,XMLReader也是一個接口:

     

     

    很容易的,我們找到XMLReaderImpl

     

     

     

    和里面的parse方法:

     

     

     

    可以看到里面選擇parse的部分,是根據是否需要Validation選擇不同的parser的實現。

     

     

    Parser的真面目已經找到啦。

    Parser2

     

     

    ValidatingParser

     

    其實,ValidatingParser也是繼承了Parser2的一個類而已,再加上了驗證合法性的功能。

     

     

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

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

    主站蜘蛛池模板: 无遮挡国产高潮视频免费观看 | 久久久无码精品亚洲日韩软件| 一级毛片aa高清免费观看| 国产AV无码专区亚洲AV毛网站| 午夜免费1000部| 一级女性全黄久久生活片免费| 亚洲欧洲一区二区| 国产a不卡片精品免费观看| 久久成人a毛片免费观看网站| 亚洲欧美中文日韩视频| 国产成人亚洲综合无码精品| 成人无码区免费视频观看| 在线观看免费播放av片| 亚洲AV成人无码网天堂| 亚洲视频日韩视频| 国产免费观看青青草原网站| 99热这里只有精品免费播放| 特级无码毛片免费视频| 亚洲国产成人无码av在线播放| 亚洲欧洲一区二区三区| 免费一本色道久久一区| 免费成人高清在线视频| 高潮毛片无遮挡高清免费视频| 亚洲国产精品张柏芝在线观看| 国产亚洲av片在线观看18女人| 最近免费中文字幕4| 久久久久久一品道精品免费看| 特级毛片在线大全免费播放| 亚洲日韩国产精品乱-久| 亚洲男人天堂2017| 国产亚洲精品激情都市| 亚洲 小说区 图片区 都市| 97无码免费人妻超级碰碰碰碰| 日本视频在线观看永久免费| 日韩在线视频免费| 亚洲精品无码少妇30P| 亚洲一欧洲中文字幕在线| 91亚洲国产成人久久精品网站| 亚洲人成网亚洲欧洲无码久久| 国产人成免费视频| 日韩视频在线免费|