DOM解析XML(二)

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

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 block
			e.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值