DOM解析XML(二)

来源:互联网 发布:工商银行网络银行 编辑:程序博客网 时间:2024/05/16 04:58

我们还是把上一篇中的实例放上来接着分析

import java.io.InputStream; import java.util.ArrayList; import java.util.List;  import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;  import org.hibernate.util.ConfigHelper;import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.Node;  public class DomParseService {     public static List<Book> getBooks(InputStream inputStream) throws Exception{         List<Book> list = new ArrayList<Book>();         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();         DocumentBuilder builder = factory.newDocumentBuilder();         //传入参数inputstream,解析指定的xml,解析完成之后会返回一个Document(这里我们可以理解成一棵树)        Document document = builder.parse(inputStream);        //或者这棵树上的元素(种类很多)        Element element = document.getDocumentElement();          NodeList bookNodes = element.getElementsByTagName("book");         for(int i=0;i<bookNodes.getLength();i++){             Element bookElement = (Element) bookNodes.item(i);             Book book = new Book();             book.setId(Integer.parseInt(bookElement.getAttribute("id")));             NodeList childNodes = bookElement.getChildNodes(); //          System.out.println("*****"+childNodes.getLength());             for(int j=0;j<childNodes.getLength();j++){                 if(childNodes.item(j).getNodeType()==Node.ELEMENT_NODE){                     if("name".equals(childNodes.item(j).getNodeName())){                         book.setName(childNodes.item(j).getFirstChild().getNodeValue());                         System.out.println("nodeValue = " + childNodes.item(j).getFirstChild().getNodeValue());                    }else if("price".equals(childNodes.item(j).getNodeName())){                         book.setPrice(Float.parseFloat(childNodes.item(j).getFirstChild().getNodeValue()));                        System.out.println("nodeValue = " + Float.parseFloat(childNodes.item(j).getFirstChild().getNodeValue()));                    }                 }             }//end for j             list.add(book);         }//end for i         return list;     }        public static void main(String[] args) {    InputStream inputStream = ConfigHelper.getResourceAsStream("/book.xml");    try {getBooks(inputStream);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}} 

上一篇中我们知道了,DocumentBuilderFactory.newInstance()最终返回的是DocumentBuilderFactoryImpl,那我们接着往下看newDocumentBuilder()方法:

/**     * Creates a new instance of a {@link javax.xml.parsers.DocumentBuilder}     * using the currently configured parameters.     */    public DocumentBuilder newDocumentBuilder()        throws ParserConfigurationException    {        /** Check that if a Schema has been specified that neither of the schema properties have been set. */        if (grammar != null && attributes != null) {            if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_LANGUAGE)) {                throw new ParserConfigurationException(                        SAXMessageFormatter.formatMessage(null,                        "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_LANGUAGE}));            }            else if (attributes.containsKey(JAXPConstants.JAXP_SCHEMA_SOURCE)) {                throw new ParserConfigurationException(                        SAXMessageFormatter.formatMessage(null,                        "schema-already-specified", new Object[] {JAXPConstants.JAXP_SCHEMA_SOURCE}));            }        }        try {            return new DocumentBuilderImpl(this, attributes, features, fSecureProcess);        } catch (SAXException se) {            // Handles both SAXNotSupportedException, SAXNotRecognizedException            throw new ParserConfigurationException(se.getMessage());        }    }

这里我们看到最终返回的实例是DocumentBuilder的实现类DocumentBuilderImpl,所以要注意这个类中对父类的实现方法

/**     * Parse the content of the given <code>InputStream</code> as an XML     * document and return a new DOM {@link Document} object.     * An <code>IllegalArgumentException</code> is thrown if the     * <code>InputStream</code> is null.     *     * @param is InputStream containing the content to be parsed.     *     * @return <code>Document</code> result of parsing the     *  <code>InputStream</code>     *     * @throws IOException If any IO errors occur.     * @throws SAXException If any parse errors occur.     * @throws IllegalArgumentException When <code>is</code> is <code>null</code>     *     * @see org.xml.sax.DocumentHandler     */        public Document parse(InputStream is)        throws SAXException, IOException {        if (is == null) {            throw new IllegalArgumentException("InputStream cannot be null");        }                InputSource in = new InputSource(is);        return parse(in);    }

/**     * Parse the content of the given input source as an XML document     * and return a new DOM {@link Document} object.     * An <code>IllegalArgumentException</code> is thrown if the     * <code>InputSource</code> is <code>null</code> null.     *     * @param is InputSource containing the content to be parsed.     *     * @return A new DOM Document object.     *     * @throws IOException If any IO errors occur.     * @throws SAXException If any parse errors occur.     * @throws IllegalArgumentException When <code>is</code> is <code>null</code>     *     * @see org.xml.sax.DocumentHandler     */        public abstract Document parse(InputSource is)        throws SAXException, IOException;

public Document parse(InputSource is) throws SAXException, IOException {        if (is == null) {            throw new IllegalArgumentException(                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,                 "jaxp-null-input-source", null));        }        if (fSchemaValidator != null) {            if (fSchemaValidationManager != null) {                fSchemaValidationManager.reset();            }            resetSchemaValidator();        }        domParser.parse(is);        return domParser.getDocument();    }

这里domParser.parse(is)调用的是XMLParser类中的方法:

/**     * parse     *     * @param inputSource     *     * @exception XNIException     * @exception java.io.IOException     */    public void parse(XMLInputSource inputSource)         throws XNIException, IOException {        reset();        fConfiguration.parse(inputSource);    } // parse(XMLInputSource) 

这里fConfiguration.parse(inputSource)方法是调用的com.sun.org.apache.xerces.internal.parsers.XML11Configuration类中的parse(XMLInputSource source)方法,为什么会调用到这里来呢,因为在实例化DOMParser对象的时候:

/**     * Constructs a DOM parser using the specified symbol table and     * grammar pool.     */    public DOMParser(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 properties        fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);        if (symbolTable != null) {            fConfiguration.setProperty(SYMBOL_TABLE, symbolTable);        }        if (grammarPool != null) {            fConfiguration.setProperty(XMLGRAMMAR_POOL, grammarPool);        }        fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES);    } // <init>(SymbolTable,XMLGrammarPool)

因为XIncludeAwareParserConfiguration类的父类为XML11Configuration类,所以就显得清晰明了:

/**     * Parses the specified input source.     *     * @param source The input source.     *     * @exception XNIException Throws exception on XNI error.     * @exception java.io.IOException Throws exception on i/o error.     */    public void parse(XMLInputSource source) throws XNIException, IOException {        if (fParseInProgress) {            // REVISIT - need to add new error message            throw new XNIException("FWK005 parse may not be called while parsing.");        }        fParseInProgress = true;        try {            setInputSource(source);            parse(true);        } catch (XNIException ex) {            if (PRINT_EXCEPTION_STACK_TRACE)                ex.printStackTrace();            throw ex;        } catch (IOException ex) {            if (PRINT_EXCEPTION_STACK_TRACE)                ex.printStackTrace();            throw ex;        } catch (RuntimeException ex) {            if (PRINT_EXCEPTION_STACK_TRACE)                ex.printStackTrace();            throw ex;        } catch (Exception ex) {            if (PRINT_EXCEPTION_STACK_TRACE)                ex.printStackTrace();            throw new XNIException(ex);        } finally {            fParseInProgress = false;            // close all streams opened by xerces            this.cleanup();        }    } // parse(InputSource)

这里面具体怎么实现的,我在再下一章好好研究一下。

总结:在查看源码的时候,我总是会出现找不到源码的情况,除了与jdk中版本不一致之外,还有个根本的原因就是java基础知识太差了,像什么子类可以直接使用父类的方法,子类重写父类的方法之后,程序会用到子类的方法等等这些基础的知识点,以前在学习或者面试的时候感觉那个时候都是背的,时间长了之后天天写CRUD,一致与现在都搞不清楚这些最基本也是最重要的知识点了,现在越来越觉得坚持看源码,虽然过程很痛苦,但是日积月累之后我的代码功力肯定会大大提高,加油。


0 0