java解析xml(sax方式)

来源:互联网 发布:开淘宝店卖什么好卖 编辑:程序博客网 时间:2024/05/16 02:27

SAX的方式,大致步骤:

在一个public static void main(String []args)方法中所执行的步骤使用SAXParserFactory 生成 SAXParser解析类。创建一个 extends DefaultHandler 的类,例如ParserDefaultHandler调用SAXParser.parse("文件路径","ParserDefaultHandler");直接可以遍历ParserDefaultHandler得到的结果。代码为:
public static void main(String []args) throws Exception{        SAXParserFactory saxPF = SAXParserFactory.newInstance();        SAXParser saxParser = saxPF.newSAXParser();        SaxParserHandler saxHandler = new SaxParserHandler();        saxParser.parse("fish.xml", saxHandler);        System.out.println("~~~~~共有"+saxHandler.getFishList().size()+"种鱼");        for (Fish fish : saxHandler.getFishList()) {        }    }

ParserDefaultHandler(继承DefaultHandler 的 类) 需要实现的方法:startDocument()----开始的标识、endDocument()-----结束的标识、startElement(String uri, String localName, String qName, Attributes attributes)----获取相关属性的操作、endElement(String uri,String localName,String qName)--存储相关对象的操作、 characters(char[] ch, int start, int length)-----进行取第几个值的方法、

以下为查看相关所关联的class:
在SAXParserImpl中的
1、 先调用父类SAXParser的parse(String uri, DefaultHandler dh)
它的逻辑代码:

public void parse(String uri, DefaultHandler dh)        throws SAXException, IOException {        if (uri == null) {            throw new IllegalArgumentException("uri cannot be null");        }        InputSource input = new InputSource(uri);        this.parse(input, dh);    }

2、 再执行父类的 parse(InputSource is, DefaultHandler dh)
逻辑代码为:

 public void parse(InputSource is, DefaultHandler dh)        throws SAXException, IOException {        if (is == null) {            throw new IllegalArgumentException("InputSource cannot be null");        }        XMLReader reader = this.getXMLReader();---继承类实现的方法        if (dh != null) {            reader.setContentHandler(dh);            reader.setEntityResolver(dh);            reader.setErrorHandler(dh);            reader.setDTDHandler(dh);        }        reader.parse(is);    }

XMLReader reader = JAXPSAXParser类的对象

为什么 JAXPSAXParser对象 可以给 XMLReader 对象,如图(不专业的关系图)所示:
JAXPSAXParser
3、reader.parse(is)的源码(JAXPSAXParser类中):

public void parse(InputSource inputSource)            throws SAXException, IOException {            if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {                if (fSAXParser.fSchemaValidationManager != null) {                    fSAXParser.fSchemaValidationManager.reset();                }                resetSchemaValidator();            }            super.parse(inputSource);        }

4、 super.parse(inputSource)源码(于AbstractSAXParser类中):

 public void parse(InputSource inputSource)        throws SAXException, IOException {        // parse document        try {            XMLInputSource xmlInputSource =                new XMLInputSource(inputSource.getPublicId(),                                   inputSource.getSystemId(),                                   null);            xmlInputSource.setByteStream(inputSource.getByteStream());            xmlInputSource.setCharacterStream(inputSource.getCharacterStream());            xmlInputSource.setEncoding(inputSource.getEncoding());            parse(xmlInputSource);        }        // wrap XNI exceptions as SAX exceptions        catch (XMLParseException e) {            Exception ex = e.getException();            if (ex == null) {                // must be a parser exception; mine it for locator info and throw                // a SAXParseException                LocatorImpl locatorImpl = new LocatorImpl() {                    public String getXMLVersion() {                        return fVersion;                    }                    // since XMLParseExceptions know nothing about encoding,                    // we cannot return anything meaningful in this context.                    // We *could* consult the LocatorProxy, but the                    // application can do this itself if it wishes to possibly                    // be mislead.                    public String getEncoding() {                        return null;                    }                };                locatorImpl.setPublicId(e.getPublicId());                locatorImpl.setSystemId(e.getExpandedSystemId());                locatorImpl.setLineNumber(e.getLineNumber());                locatorImpl.setColumnNumber(e.getColumnNumber());                throw new SAXParseException(e.getMessage(), locatorImpl);            }            if (ex instanceof SAXException) {                // why did we create an XMLParseException?                throw (SAXException)ex;            }            if (ex instanceof IOException) {                throw (IOException)ex;            }            throw new SAXException(ex);        }        catch (XNIException e) {            Exception ex = e.getException();            if (ex == null) {                throw new SAXException(e.getMessage());            }            if (ex instanceof SAXException) {                throw (SAXException)ex;            }            if (ex instanceof IOException) {                throw (IOException)ex;            }            throw new SAXException(ex);        }    } // parse(InputSource)

5、parse(xmlInputSource); 源码:

 public void parse(XMLInputSource inputSource)         throws XNIException, IOException {        reset();        fConfiguration.parse(inputSource);    } // parse(XMLInputSource) 

确认fConfiguration 是调用哪一个类的方法:
初始化 SAXParserImpl 的实例的时候,调用了 SAXParserImpl(SAXParserFactoryImpl spf, Hashtable features, boolean secureProcessing);
在该构造函数中调用 xmlReader = new JAXPSAXParser(this);
则所调用的 JAXPSAXParser 构造函数为:

 JAXPSAXParser(SAXParserImpl saxParser) {            super();            fSAXParser = saxParser;        }

super() 父类的构造函数(无参的构造函数调用了有参的构造函数):

public SAXParser() {        this(null, null);    } // <init>()public SAXParser(SymbolTable symbolTable, XMLGrammarPool grammarPool) {        super((XMLParserConfiguration)ObjectFactory.createObject(            "com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",            "com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration"            ));        // set features        fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES);        fConfiguration.setFeature(NOTIFY_BUILTIN_REFS, true);        // set properties        fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);        if (symbolTable != null) {            fConfiguration.setProperty(SYMBOL_TABLE, symbolTable);        }        if (grammarPool != null) {            fConfiguration.setProperty(XMLGRAMMAR_POOL, grammarPool);        }    } // <init>(SymbolTable,XMLGrammarPool)

调用的入参两个的构造方法中的:
super((XMLParserConfiguration)ObjectFactory.createObject(
“com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration”,
“com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration”
));

进行初始化了 XMLParserConfiguration 的对象。

 static Object createObject(String factoryId, String fallbackClassName)        throws ConfigurationError {        return createObject(factoryId, null, fallbackClassName);//传入的是所对应的父类,以及所需要传回的实际的类    } // createObject(String,String):Object
  static Object createObject(String factoryId,                                      String propertiesFilename,                                      String fallbackClassName)        throws ConfigurationError    {        if (DEBUG) debugPrintln("debug is on");        SecuritySupport ss = SecuritySupport.getInstance();        ClassLoader cl = findClassLoader();        // Use the system property first        try {            String systemProp = ss.getSystemProperty(factoryId);// 此处运用的一个方法是查找系统属性,一般是jvm系统属性,该传参为"com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",则获取到的是 null            if (systemProp != null) {                if (DEBUG) debugPrintln("found system property, value=" + systemProp);                return newInstance(systemProp, cl, true);            }        } catch (SecurityException se) {            // Ignore and continue w/ next location        }        // JAXP specific change        // always use fallback class to avoid the expense of constantly        // "stat"ing a non-existent "xerces.properties" and jar SPI entry        // see CR 6400863: Expensive creating of SAX parser in Mustang        if (true) { //这里根据所传入的 所需返回的类的参数 进行返回所需的类的实例            if (fallbackClassName == null) {                throw new ConfigurationError(                    "Provider for " + factoryId + " cannot be found", null);            }            if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);            return newInstance(fallbackClassName, cl, true);        }//接下来根据propertiesFilename 参数进行获取        // Try to read from propertiesFilename, or $java.home/lib/xerces.properties        String factoryClassName = null;        // no properties file name specified; use $JAVA_HOME/lib/xerces.properties:        if (propertiesFilename == null) {            File propertiesFile = null;            boolean propertiesFileExists = false;            try {                String javah = ss.getSystemProperty("java.home");                propertiesFilename = javah + File.separator +                    "lib" + File.separator + DEFAULT_PROPERTIES_FILENAME;                propertiesFile = new File(propertiesFilename);                propertiesFileExists = ss.getFileExists(propertiesFile);            } catch (SecurityException e) {                // try again...                fLastModified = -1;                fXercesProperties = null;            }            synchronized (ObjectFactory.class) {                boolean loadProperties = false;                FileInputStream fis = null;                try {                    // file existed last time                    if(fLastModified >= 0) {                        if(propertiesFileExists &&                                (fLastModified < (fLastModified = ss.getLastModified(propertiesFile)))) {                            loadProperties = true;                        } else {                            // file has stopped existing...                            if(!propertiesFileExists) {                                fLastModified = -1;                                fXercesProperties = null;                            } // else, file wasn't modified!                        }                    } else {                        // file has started to exist:                        if(propertiesFileExists) {                            loadProperties = true;                            fLastModified = ss.getLastModified(propertiesFile);                        } // else, nothing's changed                    }                    if(loadProperties) {                        // must never have attempted to read xerces.properties before (or it's outdeated)                        fXercesProperties = new Properties();                        fis = ss.getFileInputStream(propertiesFile);                        fXercesProperties.load(fis);                    }                } catch (Exception x) {                    fXercesProperties = null;                    fLastModified = -1;                    // assert(x instanceof FileNotFoundException                    //        || x instanceof SecurityException)                    // In both cases, ignore and continue w/ next location                }                finally {                    // try to close the input stream if one was opened.                    if (fis != null) {                        try {                            fis.close();                        }                        // Ignore the exception.                        catch (IOException exc) {}                    }                }            }            if(fXercesProperties != null) {                factoryClassName = fXercesProperties.getProperty(factoryId);            }        } else {            FileInputStream fis = null;            try {                fis = ss.getFileInputStream(new File(propertiesFilename));                Properties props = new Properties();                props.load(fis);                factoryClassName = props.getProperty(factoryId);            } catch (Exception x) {                // assert(x instanceof FileNotFoundException                //        || x instanceof SecurityException)                // In both cases, ignore and continue w/ next location            }            finally {                // try to close the input stream if one was opened.                if (fis != null) {                    try {                        fis.close();                    }                    // Ignore the exception.                    catch (IOException exc) {}                }            }        }        if (factoryClassName != null) {            if (DEBUG) debugPrintln("found in " + propertiesFilename + ", value=" + factoryClassName);            return newInstance(factoryClassName, cl, true);        }        // Try Jar Service Provider Mechanism        Object provider = findJarServiceProvider(factoryId);        if (provider != null) {            return provider;        }        if (fallbackClassName == null) {            throw new ConfigurationError(                "Provider for " + factoryId + " cannot be found", null);        }        if (DEBUG) debugPrintln("using fallback, value=" + fallbackClassName);        return newInstance(fallbackClassName, cl, true);    } // createObject(String,String,String):Object

在上面 createObject(String factoryId,
String propertiesFilename,
String fallbackClassName)中所调用的SecuritySupport的 getSystemProperty方法

  String getSystemProperty(final String propName) {        return (String)        AccessController.doPrivileged(new PrivilegedAction() {            public Object run() {                return System.getProperty(propName);//该方法是获取系统属性            }        });    }

调用的 AccessController中的 public static native T doPrivileged(PrivilegedAction action);// native的修饰,则表示外部定义.

则 获取到的实例为 XIncludeAwareParserConfiguration 类的。它与XMLParserConfiguration 类的关系(不专业的关系图)如下:
XIncludeAwareParserConfiguration

原创粉丝点击