【嘿!Java】XPath在Java中的使用和小问题
2014-08-24 09:24
176 查看
博主最近看W3School的教程http://www.w3school.com.cn/xpath/index.asp,学了一些XPath的皮毛,这里面主要讲XPath的语法,具体如何在Java代码中使用XPath则参考这篇文章Java
语言的 XPath API。
博主参考第二篇文章,首先在这里给出示例Java代码,之后会说说使用过程中的小问题。下面的代码只做到查询出NodeList这一步,查询出的结果做什么样的处理(如:读取文本等)这里暂时不讨论。
后来,博主使用这段代码时产生了新需求。上面这段代码在new MyXPath(String fileName)时,必须提供一个包括其路径文件,比如在Java工程下有一个xml文件夹,里面存放了一个author.xml文件,就要写new MyXPath("xml/author.xml");。但有时候并没有一个已经存在的现成的文件,比如:通过发送网络请求,得到xml数据,因为不想将其以文件形式存储下来,所以只有存储它的流InputStream。
博主在网上搜了一些文章,了解到上面代码中generateDocument()方法里有句
这下好办了,博主就将上面代码修改成下面这样。
问题描述
但是这段代码在运用过程中出现了一个问题:当用类似下面的代码连续解析同一个流in,会报错。
原因分析
博主在网上查了,在使用xpath解析xml时,出现IOException里找到了答案。这位博主evaluate方法用的是Object evaluate(InputSource source, QName returnType),他是这么说自己代码报错原因的:
在每次调用Object evaluate(InputSource source, QName returnType)这个方法时都会重新生成DocumentBuilder对象来parse InputSource,每次parse都会把整个文件都解析成dom树并load到内存中,然后关闭流,在第二次parse同一个Inputsource的时候便产生了IOException。
博主用的是Object evaluate(Document doc, QName returnType),与上面不一样,但根据这个说法类推——博主的代码里每次调用XPathUtils.queryNodelist()都会执行一次generateDocument(in),里面有一句doc = builder.parse(in);,可以猜测这句话执行完会关闭流,所以对同一个流in再次调用XPathInputStream.queryNodelist();时,in已经被关闭,造成报错。
博主没有看XPath的源代码,这只是自己猜想,如果哪位大神知道真正的原因,告诉博主呀~~
解决办法
博主猜测上面的原因后,想如果连续同一个流in,只调用一次doc = builder.parse(in);,是不是就不会报错了呢?为此,博主修改了代码,实验了之后发现真的没有再报错,说明博主猜想应该没有错。
连续调用代码如下,不会报错
语言的 XPath API。
博主参考第二篇文章,首先在这里给出示例Java代码,之后会说说使用过程中的小问题。下面的代码只做到查询出NodeList这一步,查询出的结果做什么样的处理(如:读取文本等)这里暂时不讨论。
后来,博主使用这段代码时产生了新需求。上面这段代码在new MyXPath(String fileName)时,必须提供一个包括其路径文件,比如在Java工程下有一个xml文件夹,里面存放了一个author.xml文件,就要写new MyXPath("xml/author.xml");。但有时候并没有一个已经存在的现成的文件,比如:通过发送网络请求,得到xml数据,因为不想将其以文件形式存储下来,所以只有存储它的流InputStream。
博主在网上搜了一些文章,了解到上面代码中generateDocument()方法里有句
doc = builder.parse(fileName);这里fileName是形如"xml/author.xml"的字符串,其实这句parse()方法的参数也可以是InputStream类的
这下好办了,博主就将上面代码修改成下面这样。
import java.io.IOException; import java.io.InputStream; import java.lang.Double; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; public class XPathInputStream { public XPath generateXPath() { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); return xpath; } public Document generateDocument(InputStream in) { DocumentBuilder builder = generateDocumentBuilder(); Document doc = null; try { doc = builder.parse(in); } catch (Exception e) { e.printStackTrace(); } return doc; } public DocumentBuilder generateDocumentBuilder() { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true);// never forget this! DocumentBuilder builder = null; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { e.printStackTrace(); } return builder; } /** * 查询节点集 * @param in 待查询的输入流 * @param exprString XPath查询语句 * return 查询到的节点集 */ public NodeList queryNodelist(InputStream in,String exprString) { NodeList nodes = null; XPath xpath=generateXPath(); Document doc=generateDocument(in); try { XPathExpression expr = xpath.compile(exprString);//用XPath对象编译 XPath表达式 /*计算XPath表达式得到结果 *表达式是针对特定的上下文节点计算的,在这个例子中是整个文档 *还必须指定返回类型。这里要求返回一个节点集 */ result = expr.evaluate(doc, XPathConstants.NODESET); nodes = (NodeList) result;//将结果强制转化成NodeList } catch (XPathExpressionException e) { e.printStackTrace(); } return nodes; } }
问题描述
但是这段代码在运用过程中出现了一个问题:当用类似下面的代码连续解析同一个流in,会报错。
XPathInputStream.queryNodelist(in, "//disambiguation[1]/organization"); XPathInputStream.queryNodelist(in, "//interest/keyword");
原因分析
博主在网上查了,在使用xpath解析xml时,出现IOException里找到了答案。这位博主evaluate方法用的是Object evaluate(InputSource source, QName returnType),他是这么说自己代码报错原因的:
在每次调用Object evaluate(InputSource source, QName returnType)这个方法时都会重新生成DocumentBuilder对象来parse InputSource,每次parse都会把整个文件都解析成dom树并load到内存中,然后关闭流,在第二次parse同一个Inputsource的时候便产生了IOException。
博主用的是Object evaluate(Document doc, QName returnType),与上面不一样,但根据这个说法类推——博主的代码里每次调用XPathUtils.queryNodelist()都会执行一次generateDocument(in),里面有一句doc = builder.parse(in);,可以猜测这句话执行完会关闭流,所以对同一个流in再次调用XPathInputStream.queryNodelist();时,in已经被关闭,造成报错。
博主没有看XPath的源代码,这只是自己猜想,如果哪位大神知道真正的原因,告诉博主呀~~
解决办法
博主猜测上面的原因后,想如果连续同一个流in,只调用一次doc = builder.parse(in);,是不是就不会报错了呢?为此,博主修改了代码,实验了之后发现真的没有再报错,说明博主猜想应该没有错。
连续调用代码如下,不会报错
MyXPathInputStream.queryNodelist("//disambiguation[1]/organization"); MyXPathInputStream.queryNodelist("//interest/keyword");
相关文章推荐
- Java 读取XML时使用XPath的问题
- Eclipse下使用Java Properties文件的中文问题
- Java路径问题最终解决方案使用演示
- 关于Linux 下 使用JAVA出现中文小框框的问题
- Java下应用XFire的项目使用Proguard混淆时遇到的问题
- jaVA使用FTP上传下载文件的问题
- JAVA程序开发小经验 - 使用ObjectStream会出现的问题
- 关于JSTL下使用xpath出错的问题
- 使用Spring的javamail注意的中文问题
- Java中使用Graphics 画图的一个问题
- 使用Eclipse3.2.1+STP.0.4.0+Apache Tuscany开发SCA的Java组件(4)安装运行错误问题修正篇
- Java路径问题最终解决方案使用演示
- JAVA Web 安全机制----使用filter验证session用户和页面缓存问题处理
- Java路径问题最终解决方案使用演示
- 使用Spring的javamail注意的中文问题
- 在Java中使用循环定义会出现哪些问题
- 使用maven构建项目java.nio.BufferOverflowException问题的解决
- 解决Java读取properties文件的中文问题的新办法(不使用native2ascii.exe及其他工具)
- 使用网上流传的一个数据库连接池在Proxy.newProxyInstance处引起 java.lang.ClassCastException 问题的解决方法
- CheckStyle使用java.header文件的问题