DOM解析XML(一)
来源:互联网 发布:lte优化工程师前景 编辑:程序博客网 时间:2024/05/16 05:46
1、什么是DOM
DOM-Document Object Model. 简称:文档对象模型。我听到这个词还是不知道什么意思。它其实主要用来解析XML与HTML文档。它的解析方式是一开始会加载整个XML文档,然后对这些文档进行树形结构的搭建。在实际工作中,它适合针对小而且频繁使用的XML文档。
2、新建Book.xml
<?xml version="1.0" encoding="UTF-8"?> <books> <book id="12"> <name>thinking in java</name> <price>85.5</price> </book> <book id="15"> <name>Spring in Action</name> <price>39.0</price> </book> </books>
3、编写简单测试例子
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();}}}
4、首先看看如何获得DocumentBuilderFactory对象,这里面用到了类加载的知识,有人说这是工作模式,实话说我没太明白啥是工厂模式,不多说,解读源码:
/** * Obtain a new instance of a * <code>DocumentBuilderFactory</code>. This static method creates * a new factory instance. * This method uses the following ordered lookup procedure to determine * the <code>DocumentBuilderFactory</code> implementation class to * load: * <ul> * <li> * Use the <code>javax.xml.parsers.DocumentBuilderFactory</code> system * property. * </li> * <li> * Use the properties file "lib/jaxp.properties" in the JRE directory. * This configuration file is in standard <code>java.util.Properties * </code> format and contains the fully qualified name of the * implementation class with the key being the system property defined * above. * * The jaxp.properties file is read only once by the JAXP implementation * and it's values are then cached for future use. If the file does not exist * when the first attempt is made to read from it, no further attempts are * made to check for its existence. It is not possible to change the value * of any property in jaxp.properties after it has been read for the first time. * </li> * <li> * Use the Services API (as detailed in the JAR specification), if * available, to determine the classname. The Services API will look * for a classname in the file * <code>META-INF/services/javax.xml.parsers.DocumentBuilderFactory</code> * in jars available to the runtime. * </li> * <li> * Platform default <code>DocumentBuilderFactory</code> instance. * </li> * </ul> * * Once an application has obtained a reference to a * <code>DocumentBuilderFactory</code> it can use the factory to * configure and obtain parser instances. * * * <h2>Tip for Trouble-shooting</h2> * <p>Setting the <code>jaxp.debug</code> system property will cause * this method to print a lot of debug messages * to <code>System.err</code> about what it is doing and where it is looking at.</p> * * <p> If you have problems loading {@link DocumentBuilder}s, try:</p> * <pre> * java -Djaxp.debug=1 YourProgram .... * </pre> * * @return New instance of a <code>DocumentBuilderFactory</code> * * @throws FactoryConfigurationError if the implementation is not * available or cannot be instantiated. */ public static DocumentBuilderFactory newInstance() { try { return (DocumentBuilderFactory) FactoryFinder.find( /* The default property name according to the JAXP spec */ "javax.xml.parsers.DocumentBuilderFactory", /* The fallback implementation class name */ "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"); } catch (FactoryFinder.ConfigurationError e) { throw new FactoryConfigurationError(e.getException(), e.getMessage()); } }
/** * Finds the implementation Class object in the specified order. Main * entry point. * @return Class object of factory, never null * * @param factoryId Name of the factory to find, same as * a property name * @param fallbackClassName Implementation class name, if nothing else * is found. Use null to mean no fallback. * * Package private so this code can be shared. */ static Object find(String factoryId, String fallbackClassName) throws ConfigurationError { dPrint("find factoryId =" + factoryId); // Use the system property first try { String systemProp = ss.getSystemProperty(factoryId); if (systemProp != null) { dPrint("found system property, value=" + systemProp); return newInstance(systemProp, null, true); } } catch (SecurityException se) { if (debug) se.printStackTrace(); } // try to read from $java.home/lib/jaxp.properties try { String factoryClassName = null; if (firstTime) { synchronized (cacheProps) { if (firstTime) { String configFile = ss.getSystemProperty("java.home") + File.separator + "lib" + File.separator + "jaxp.properties"; File f = new File(configFile); firstTime = false; if (ss.doesFileExist(f)) { dPrint("Read properties file "+f); cacheProps.load(ss.getFileInputStream(f)); } } } } factoryClassName = cacheProps.getProperty(factoryId); if (factoryClassName != null) { dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName); return newInstance(factoryClassName, null, true); } } catch (Exception ex) { if (debug) ex.printStackTrace(); } // 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); } dPrint("loaded from fallback value: " + fallbackClassName); return newInstance(fallbackClassName, null, true); }
我之所以把注释都放上来,是因为我每次看完源码之后再去看这些注释,总有一种原来是这样的感觉,羡慕英文好的同学,我想他们在看源码的时候速度一般会快很多,上面真正有效执行的是最后一句:
/** * Create an instance of a class. Delegates to method * <code>getProviderClass()</code> in order to load the class. * * @param className Name of the concrete class corresponding to the * service provider * * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code> * current <code>Thread</code>'s context classLoader is used to load the factory class. * * @param doFallback True if the current ClassLoader should be tried as * a fallback if the class is not found using cl */ static Object newInstance(String className, ClassLoader cl, boolean doFallback) throws ConfigurationError { return newInstance(className, cl, doFallback, false); }
/** * Create an instance of a class. Delegates to method * <code>getProviderClass()</code> in order to load the class. * * @param className Name of the concrete class corresponding to the * service provider * * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code> * current <code>Thread</code>'s context classLoader is used to load the factory class. * * @param doFallback True if the current ClassLoader should be tried as * a fallback if the class is not found using cl * * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader. */ static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader) throws ConfigurationError { try { Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader); Object instance = providerClass.newInstance(); if (debug) { // Extra check to avoid computing cl strings dPrint("created new instance of " + providerClass + " using ClassLoader: " + cl); } return instance; } catch (ClassNotFoundException x) { throw new ConfigurationError( "Provider " + className + " not found", x); } catch (Exception x) { throw new ConfigurationError( "Provider " + className + " could not be instantiated: " + x, x); } }
/** * Attempt to load a class using the class loader supplied. If that fails * and fall back is enabled, the current (i.e. bootstrap) class loader is * tried. * * If the class loader supplied is <code>null</code>, first try using the * context class loader followed by the current (i.e. bootstrap) class * loader. * * Use bootstrap classLoader if cl = null and useBSClsLoader is true */ static private Class getProviderClass(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException { try { if (cl == null) { if (useBSClsLoader) { return Class.forName(className, true, FactoryFinder.class.getClassLoader()); } else { cl = ss.getContextClassLoader(); if (cl == null) { throw new ClassNotFoundException(); } else { return cl.loadClass(className); } } } else { return cl.loadClass(className); } } catch (ClassNotFoundException e1) { if (doFallback) { // Use current class loader - should always be bootstrap CL return Class.forName(className, true, FactoryFinder.class.getClassLoader()); } else { throw e1; } } }
我们好好看看这个方法,ClassLoader是通过获取上下文Loader而来,执行完cl = ss.getContextClassLoader();之后返回的对象为:sun.misc.Launcher$AppClassLoaderw
我在学习深入探讨java类加载器的时候,知道AppClassLoaderw 属于类加载器加载而来,在他的上面有扩展类加载器,扩展类加载器上面有引导类加载器
由于我们传入的className为:com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl,所以最终返回的对象为:DocumentBuilderFactoryImpl
我们接着把类具体加载看完:
/** * Loads the class with the specified <a href="#name">binary name</a>. * This method searches for classes in the same manner as the {@link * #loadClass(String, boolean)} method. It is invoked by the Java virtual * machine to resolve class references. Invoking this method is equivalent * to invoking {@link #loadClass(String, boolean) <tt>loadClass(name, * false)</tt>}. </p> * * @param name * The <a href="#name">binary name</a> of the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException * If the class was not found */ public Class<?> loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); }
/** * Loads the class with the specified <a href="#name">binary name</a>. The * default implementation of this method searches for classes in the * following order: * * <p><ol> * * <li><p> Invoke {@link #findLoadedClass(String)} to check if the class * has already been loaded. </p></li> * * <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method * on the parent class loader. If the parent is <tt>null</tt> the class * loader built-in to the virtual machine is used, instead. </p></li> * * <li><p> Invoke the {@link #findClass(String)} method to find the * class. </p></li> * * </ol> * * <p> If the class was found using the above steps, and the * <tt>resolve</tt> flag is true, this method will then invoke the {@link * #resolveClass(Class)} method on the resulting <tt>Class</tt> object. * * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link * #findClass(String)}, rather than this method. </p> * * <p> Unless overridden, this method synchronizes on the result of * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method * during the entire class loading process. * * @param name * The <a href="#name">binary name</a> of the class * * @param resolve * If <tt>true</tt> then resolve the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException * If the class could not be found */ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
/** * Returns the class with the given <a href="#name">binary name</a> if this * loader has been recorded by the Java virtual machine as an initiating * loader of a class with that <a href="#name">binary name</a>. Otherwise * <tt>null</tt> is returned. </p> * * @param name * The <a href="#name">binary name</a> of the class * * @return The <tt>Class</tt> object, or <tt>null</tt> if the class has * not been loaded * * @since 1.1 */ protected final Class<?> findLoadedClass(String name) { if (!checkName(name)) return null; return findLoadedClass0(name); }
private native final Class findLoadedClass0(String name);
类具体如何加载这里由虚拟机和底层操作系统具体去做
0 0
- DOM解析XML(一)
- XML解析(一):DOM解析
- 一、DOM解析XML
- DOM解析xml练习(一)
- 使用DOM解析XML(一)
- XML初识(一)--使用DOM解析XML数据
- XML解析技术初探(一):DOM解析
- xml的解析方式(一)DOM 解析
- XML(DOM)解析
- java 解析XML文件(DOM & SAX)(一)
- JAVA解析XML文件(一)---DOM方式
- XML解析(二),DOM解析XML
- DOM解析XML文件实例(一)
- Android DOM 解析 XML样式一
- java解析与生成xml(一): Dom
- Java之xml文件解析一(DOM方式解析xml文件)
- XML(一) DOM解析XML文档实例一
- dom解析xml(转)
- 横竖屏切换时的activity的生命周期
- FPGA问答
- JAVA_MD5加密,SHA-1加密工具类
- 常用的矩阵求导
- Runtime执行某一个程序
- DOM解析XML(一)
- 用c++写的简易学生通讯录
- unpack
- 远程传文件
- mssqlserver 复制拷贝附件sql脚本(二)之异地服务器导出
- Quick-cocos2d-x 与COCOS2DX 区别
- getContextPath
- 什么是大型机和小型机
- 关于fragment 中onActivityResult()回调的问题