- 浏览: 471701 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
Source_野驴:
...
jsp静态化和伪静态化 -
zidanzzg:
很好的知识,找到了利用异或交换数值的理论支持,谢谢分享
XOR的性质和运算 -
ueseu:
引用(2) DomainDomain域名也是Cookie的一部 ...
Cookie的组成 -
ueseu:
引用Secure取true或者false值。如果为true,那 ...
Cookie的组成 -
liqi___123:
理解得很透彻,谢谢!!
ROLAP、MOLAP和HOLAP联机分析处理区别
如果要告诉别人买一加仑牛奶,您会怎么说?“请去买一加仑牛奶回来” 还是 “从前门出去,向左转,走三个街区向右转,再走半个街区向右转进入商店。走向四号通道,沿通道走五米向左,拿一瓶一加仑装的牛奶然后到收银台付款。再沿原路回家。” 简直太可笑了。只要在 “请去买一加仑牛奶回来” 的基础上稍加指示,多数成人都能自己买回牛奶来。
查询语言和计算机搜索与此类似。直接说 “找一个 Cryptonomicon 的副本” 要比编写搜索某个数据库的详细逻辑容易得多。由于搜索操作的逻辑非常相似,可以发明一种通用语言让您使用 “找到 Neal Stephenson 的所有著作” 这样的命令,然后编写对特定数据存储执行此类查询的引擎。
在众多查询语言之中,结构化查询语言(SQL)是一种针对查询特定类型的关系库而设计和优化的语言。其他不那么常见的查询语言还有对象查询语言(OQL)和 XQuery。但本文的主题是 XPath,一种为查询 XML 文档而设计的查询语言。比如,下面这个简单的 XPath 查询可以在文档中找到作者为 Neal Stephenson 的所有图书的标题:
//book[author="Neal Stephenson"]/title |
作为对照,查询同样信息的纯 DOM 搜索代码如 清单 1 所示:
清单 1. 找到 Neal Stephenson 所有著作 title 元素的 DOM 代码
ArrayList result = new ArrayList(); NodeList books = doc.getElementsByTagName("book"); for (int i = 0; i < books.getLength(); i++) { Element book = (Element) books.item(i); NodeList authors = book.getElementsByTagName("author"); boolean stephenson = false; for (int j = 0; j < authors.getLength(); j++) { Element author = (Element) authors.item(j); NodeList children = author.getChildNodes(); StringBuffer sb = new StringBuffer(); for (int k = 0; k < children.getLength(); k++) { Node child = children.item(k); // really should to do this recursively if (child.getNodeType() == Node.TEXT_NODE) { sb.append(child.getNodeValue()); } } if (sb.toString().equals("Neal Stephenson")) { stephenson = true; break; } } if (stephenson) { NodeList titles = book.getElementsByTagName("title"); for (int j = 0; j < titles.getLength(); j++) { result.add(titles.item(j)); } } } |
不论您是否相信,清单 1 中的 DOM 显然不如简单的 XPath 表达式通用或者健壮。您愿意编写、调试和维护哪一个?我想答案很明显。
但是虽然有很强的表达能力,XPath 并不是 Java 语言,事实上 XPath 不是一种完整的编程语言。有很多东西用 XPath 表达不出来,甚至有些查询也无法表达。比方说,XPath 不能查找国际标准图书编码(ISBN)检验码不匹配的所有图书,或者找出境外帐户数据库显示欠帐的所有作者。幸运的是,可以把 XPath 结合到 Java 程序中,这样就能发挥两者的优势了:Java 做 Java 所擅长的,XPath 做 XPath 所擅长的。
直到最近,Java 程序执行 XPath 查询所需要的应用程序编程接口(API)还因形形色色的 XPath 引擎而各不相同。Xalan 有一种 API,Saxon 使用另一种,其他引擎则使用其他的 API。这意味着代码往往把您限制到一种产品上。理想情况下,最好能够试验具有不同性能特点的各种引擎,而不会带来不适当的麻烦或者重新编写代码。
于是,Java 5 推出了 javax.xml.xpath
包,提供一个引擎和对象模型独立的 XPath 库。这个包也可用于
Java 1.3 及以后的版本,但需要单独安装 Java API for XML Processing (JAXP) 1.3。Xalan 2.7 和 Saxon
8 以及其他产品包含了这个库的实现。
我将举例说明如何使用它。然后再讨论一些细节问题。假设要查询一个图书列表,寻找 Neal Stephenson 的著作。具体来说,这个图书列表的形式如 清单 2 所示:
清单 2. 包含图书信息的 XML 文档
<inventory> <book year="2000"> <title>Snow Crash</title> <author>Neal Stephenson</author> <publisher>Spectra</publisher> <isbn>0553380958</isbn> <price>14.95</price> </book> <book year="2005"> <title>Burning Tower</title> <author>Larry Niven</author> <author>Jerry Pournelle</author> <publisher>Pocket</publisher> <isbn>0743416910</isbn> <price>5.99</price> <book> <book year="1995"> <title>Zodiac</title> <author>Neal Stephenson<author> <publisher>Spectra</publisher> <isbn>0553573862</isbn> <price>7.50</price> <book> <!-- more books... --> </inventory> |
抽象工厂
XPathFactory
是一个抽象工厂。抽象工厂设计模式使得这一种 API 能够支持不同的对象模型,如 DOM、JDOM 和
XOM。为了选择不同的模型,需要向 XPathFactory.newInstance()
方法传递标识对象模型的统一资源标识符(URI)。比如 http://xom.nu/ 可以选择 XOM。但实际上,到目前为止 DOM 是该 API
支持的惟一对象模型。
查找所有图书的 XPath 查询非常简单://book[author="Neal
Stephenson"]
。为了找出这些图书的标题,只要增加一步,表达式就变成了 //book[author="Neal
Stephenson"]/title
。最后,真正需要的是 title
元素的文本节点孩子。这就要求再增加一步,完整的表达式就是 //book[author="Neal
Stephenson"]/title/text()
。
现在我提供一个简单的程序,它从 Java 语言中执行这个查询,然后把找到的所有图书的标题打印出来。首先,需要将文档加载到一个 DOM
Document
对象中。为了简化起见,假设该文档在当前工作目录的 books.xml 文件中。下面的简单代码片段解析文档并建立对应的
Document
对象:
清单 3. 用 JAXP 解析文档
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // never forget this! DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse("books.xml"); |
到目前为止,这仅仅是标准的 JAXP 和 DOM,没有什么新鲜的。
接下来创建 XPathFactory
:
XPathFactory factory = XPathFactory.newInstance(); |
然后使用这个工厂创建 XPath
对象:
XPath xpath = factory.newXPath(); |
XPath
对象编译 XPath 表达式:
PathExpression expr = xpath.compile("//book[author='Neal Stephenson']/title/text()"); |
直接求值
如果 XPath 表达式只使用一次,可以跳过编译步骤直接对 XPath
对象调用 evaluate()
方法。但是,如果同一个表达式要重复使用多次,编译可能更快一些。
最后,计算 XPath 表达式得到结果。表达式是针对特定的上下文节点计算的,在这个例子中是整个文档。还必须指定返回类型。这里要求返回一个节点集:
Object result = expr.evaluate(doc, XPathConstants.NODESET); |
可以将结果强制转化成 DOM NodeList
,然后遍历列表得到所有的标题:
NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getNodeValue()); } |
清单 4 把上述片段组合到了一个程序中。还要注意,这些方法可能抛出一些检查异常,这些异常必须在
throws
子句中声明,但是我在上面把它们掩盖起来了:
清单 4. 用固定的 XPath 表达式查询 XML 文档的完整程序
import java.io.IOException; import org.w3c.dom.*; import org.xml.sax.SAXException; import javax.xml.parsers.*; import javax.xml.xpath.*; public class XPathExample { public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, XPathExpressionException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); // never forget this! DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("books.xml"); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr = xpath.compile("//book[author='Neal Stephenson']/title/text()"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getNodeValue()); } } } |
每当混合使用诸如 XPath 和 Java 这样两种不同的语言时,必定会有某些将两者粘合在一起的明显接缝。并非一切都很合拍。XPath 和 Java 语言没有同样的类型系统。XPath 1.0 只有四种基本数据类型:
- node-set
- number
- boolean
- string
当然,Java 语言有更多的数据类型,包括用户定义的对象类型。
多数 XPath 表达式,特别是位置路径,都返回节点集。但是还有其他可能。比如,XPath 表达式 count(//book)
返回文档中的图书数量。XPath 表达式 count(//book[@author="Neal Stephenson"]) >
10
返回一个布尔值:如果文档中 Neal Stephenson 的著作超过 10 本则返回 true,否则返回 false。
evaluate()
方法被声明为返回 Object
。实际返回什么依赖于 XPath
表达式的结果以及要求的类型。一般来说,XPath 的
- number 映射为
java.lang.Double
- string 映射为
java.lang.String
- boolean 映射为
java.lang.Boolean
- node-set 映射为
org.w3c.dom.NodeList
XPath 2
前面一直假设您使用的是 XPath 1.0。XPath 2 大大扩展和修改了类型系统。Java XPath API 支持 XPath 2 所需的主要修改是为返回 XPath 2 新数据类型增加常量。
在 Java 中计算 XPath 表达式时,第二个参数指定需要的返回类型。有五种可能,都在
javax.xml.xpath.XPathConstants
类中命名了常量:
-
XPathConstants.NODESET
-
XPathConstants.BOOLEAN
-
XPathConstants.NUMBER
-
XPathConstants.STRING
-
XPathConstants.NODE
最后一个 XPathConstants.NODE
实际上没有匹配的 XPath 类型。只有知道 XPath
表达式只返回一个节点或者只需要一个节点时才使用它。如果 XPath 表达式返回了多个节点并且指定了
XPathConstants.NODE
,则 evaluate()
按照文档顺序返回第一个节点。如果
XPath 表达式选择了一个空集并指定了 XPathConstants.NODE
,则 evaluate()
返回 null。
如果不能完成要求的转换,evaluate()
将抛出 XPathException
。
若 XML 文档中的元素在名称空间中,查询该文档的 XPath 表达式必须使用相同的名称空间。XPath 表达式不一定要使用相同的前缀,只需要名称空间 URI 相同即可。事实上,如果 XML 文档使用默认名称空间,那么尽管目标文档没有使用前缀,XPath 表达式也必须使用前缀。
但是,Java 程序不是 XML 文档,因此不能用一般的名称空间解析。必须提供一个对象将前缀映射到名称空间 URI。该对象是
javax.xml.namespace.NamespaceContext
接口的实例。比如,假设图书文档放在
http://www.example.com/books 名称空间中,如 清单 5 所示:
清单 5. 使用默认名称空间的 XML 文档
<inventory xmlns="http://www.example.com/books"> <book year="2000"> <title>Snow Crash</title> <author>Neal Stephenson</author> <publisher>Spectra</publisher> <isbn>0553380958</isbn> <price>14.95<price> </book> <!-- more books... --> <inventory> |
查找 Neal Stephenson 全部著作标题的 XPath 表达式就要改为 //pre:book[pre:author="Neal
Stephenson"]/pre:title/text()
。但是,必须将前缀 pre
映射到 URI
http://www.example.com/books。NamespaceContext
接口在 Java
软件开发工具箱(JDK)或 JAXP 中没有默认实现似乎有点笨,但确实如此。不过,自己实现也不难。清单 6
对一个名称空间给出了简单的实现。还需要映射 xml
前缀。
清单 6. 绑定一个名称空间和默认名称空间的简单上下文
import java.util.Iterator; import javax.xml.*; import javax.xml.namespace.NamespaceContext; public class PersonalNamespaceContext implements NamespaceContext { public String getNamespaceURI(String prefix) { if (prefix == null) throw new NullPointerException("Null prefix"); else if ("pre".equals(prefix)) return "http://www.example.org/books"; else if ("xml".equals(prefix)) return XMLConstants.XML_NS_URI; return XMLConstants.NULL_NS_URI; } // This method isn't necessary for XPath processing. public String getPrefix(String uri) { throw new UnsupportedOperationException(); } // This method isn't necessary for XPath processing either. public Iterator getPrefixes(String uri) { throw new UnsupportedOperationException(); } } |
使用映射存储绑定和增加 setter 方法实现名称空间上下文的重用也不难。
创建 NamespaceContext
对象后,在编译表达式之前将其安装到 XPath
对象上。以后就可以像以前一样是用这些前缀查询了。比如:
清单 7. 使用名称空间的 XPath 查询
XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); xpath.setNamespaceContext(new PersonalNamespaceContext()); XPathExpression expr = xpath.compile("//pre:book[pre:author='Neal Stephenson']/pre:title/text()"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; for (int i = 0; i < nodes.getLength(); i++) { System.out.println(nodes.item(i).getNodeValue()); } |
有时候,在 Java 语言中定义用于 XPath 表达式的扩展函数很有用。这些函数可以执行用纯 XPath 很难或者无法执行的任务。不过必须是真正的函数,而不是随意的方法。就是说不能有副作用。(XPath 函数可以按照任意的顺序求值任意多次。)
通过 Java XPath API 访问的扩展函数必须实现 javax.xml.xpath.XPathFunction
接口。这个接口只声明了一个方法 evaluate:
public Object evaluate(List args) throws XPathFunctionException |
该方法必须返回 Java 语言能够转换到 XPath 的五种类型之一:
-
String
-
Double
-
Boolean
-
Nodelist
-
Node
比如,清单 8 显示了一个扩展函数,它检查 ISBN 的校验和并返回
Boolean
。这个校验和的基本规则是前九位数的每一位乘上它的位置(即第一位数乘上 1,第二位数乘上
2,依次类推)。将这些数加起来然后取除以 11 的余数。如果余数是 10,那么最后一位数就是 X。
清单 8. 检查 ISBN 的 XPath 扩展函数
import java.util.List; import javax.xml.xpath.*; import org.w3c.dom.*; public class ISBNValidator implements XPathFunction { // This class could easily be implemented as a Singleton. public Object evaluate(List args) throws XPathFunctionException { if (args.size() != 1) { throw new XPathFunctionException("Wrong number of arguments to valid-isbn()"); } String isbn; Object o = args.get(0); // perform conversions if (o instanceof String) isbn = (String) args.get(0); else if (o instanceof Boolean) isbn = o.toString(); else if (o instanceof Double) isbn = o.toString(); else if (o instanceof NodeList) { NodeList list = (NodeList) o; Node node = list.item(0); // getTextContent is available in Java 5 and DOM 3. // In Java 1.4 and DOM 2, you'd need to recursively // accumulate the content. isbn= node.getTextContent(); } else { throw new XPathFunctionException("Could not convert argument type"); } char[] data = isbn.toCharArray(); if (data.length != 10) return Boolean.FALSE; int checksum = 0; for (int i = 0; i < 9; i++) { checksum += (i+1) * (data[i]-'0'); } int checkdigit = checksum % 11; if (checkdigit + '0' == data[9] || (data[9] == 'X' && checkdigit == 10)) { return Boolean.TRUE; } return Boolean.FALSE; } } |
下一步让这个扩展函数能够在 Java 程序中使用。为此,需要在编译表达式之前向 XPath 对象安装
javax.xml.xpath.XPathFunctionResolver
。函数求解器将函数的 XPath 名称和名称空间 URI
映射到实现该函数的 Java 类。清单 9 是一个简单的函数求解器,将扩展函数
valid-isbn
和名称空间 http://www.example.org/books 映射到 清单 8 中的类。比如,XPath 表达式
//book[not(pre:valid-isbn(isbn))]
可以找到 ISBN 校验和不匹配的所有图书。
清单 9. 识别 valid-isbn 扩展函数的上下文
iimport javax.xml.namespace.QName; import javax.xml.xpath.*; public class ISBNFunctionContext implements XPathFunctionResolver { private static final QName name = new QName("http://www.example.org/books", "valid-isbn"); public XPathFunction resolveFunction(QName name, int arity) { if (name.equals(ISBNFunctionContext.name) && arity == 1) { return new ISBNValidator(); } return null; } } |
由于扩展函数必须有名称空间,所以计算包含扩展函数的表达式时必须使用
NamespaceResolver
,即便查询的文档没有使用任何名称空间。由于
XPathFunctionResolver
、XPathFunction
和
NamespaceResolver
都是接口,如果方便的话可以将它们放在所有的类中。
用 SQL 和 XPath 这样的声明性语言编写查询,要比使用 Java 和 C 这样的命令式语言容易得多。但是,用 Java 和 C
这样的图灵完整语言编写复杂的逻辑,又比 SQL 和 XPath 这样的声明性语言容易得多。所幸的是,通过使用 Java Database
Connectivity (JDBC) 和 javax.xml.xpath
之类的 API
可以将两者结合起来。随着世界上越来越多的数据转向 XML,javax.xml.xpath
将与
java.sql
一样变得越来越重要。
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
- “Get
started with XPath 2.0”(Benoît Marchal,developerWorks,2006 年 5 月):XPath 2.0
提供了更强大的功能和更高的效率,了解如何利用这一新的数据模型编写更复杂的请求。
- “Working
with JAXP namespace contexts”:Norm Walsh 为名称空间上下文辩解。
-
XML in a
Nutshell(Elliotte Rusty Harold 和 W. Scott Means,O'Reilly,2005 年):关于
XPath 1.0 以及 DOM 和 JAXP 的完整参考和简明指南。
-
developerWorks Java
技术专区:提供了关于 Java 编程方方面面的数百篇文章。
-
IBM XML 1.1
认证:了解如何才能成为一名 IBM 认证的 XML 1.1 及相关技术的开发人员。
-
XML:developerWorks
XML 专区提供了各种技术文章和技巧、教程、标准和 IBM 红皮书。
-
developerWorks
技术事件和网络广播:随时关注技术的最新进展。
获得产品和技术
-
JAXP Project:从 java.net
下载 JAXP 1.3 for Java 1.3 和 1.4。
-
Xalan 2:看看来自 Apache Project
的支持本文中所述 XPath API 的 XSLT 引擎。
-
SAXON 8:试一试 Michael Kay 的 XSLT
引擎,它也支持本文所讨论的 XPath API。
-
IBM
试用软件:用这些试用软件开发您的下一个项目,这些软件可直接从 developerWorks 下载。
发表评论
-
java String.getBytes()编码问题 (讲到实处了)
2012-12-12 11:26 758转载自: String.getBytes()的问 ... -
JSP中文验证码
2012-05-14 17:18 1211以上两篇文章的内容介绍了有关JSP中产生数字验证码跟中文验证 ... -
One-Jar之旅
2011-09-16 10:06 1727One-Jar之旅 1 ... -
Javamail中的常见中文乱码问题与解决办法
2011-09-09 09:48 1569在使用javamail api开发邮件服务系统时,我们常常会碰 ... -
理解Java ClassLoader机制
2011-07-28 11:24 1342再次阅读这篇文章时,有了更深的体会,特转载之。 理解Ja ... -
JAVA泛型简介
2011-07-22 13:41 1187另篇:http://www.java3z.com/cwbweb ... -
BCEL和Javassist的介绍
2011-07-18 10:49 1532BCEL 介绍: Byte Code E ... -
类加载器特技:OSGi代码生成
2011-07-18 10:08 726转自:http://www.oschina.n ... -
开源的java编译器jikes
2011-06-19 08:50 2197今天才知道java编译器还有个jikes这样的开源产品。 ... -
java的沙盒机制
2011-01-28 18:03 2009JAVA 的安全模型不同于传统的安全方法,传统的安全方法中 ... -
filter的调用顺序
2011-01-06 11:54 1249在一个大型项目中往往有多个servlet过滤器,但是这些ser ... -
JAVA操作COOKIE
2010-12-28 11:32 12371.设置Cookie Cookie cookie = ... -
关于volatile变量的理解
2010-12-12 13:21 967前些日子在看些多线 ... -
关于Java 构造函数和继续特性的回顾
2010-12-06 09:21 1152java构造函数 java类库的设计者们通过提供 ... -
Java可变参数方法重载的错误3例
2010-12-05 23:28 1079JDK1.5引进了方法的可变参数,受到许多开发人员的青睐。 ... -
JDK1.5新特性
2010-12-05 23:19 680"JDK1.5"的一个重要主题就是 ... -
序列化中serialVersionUID的使用
2010-12-04 08:39 1300先来看一个例子: 定义一个bean: Java代码 ... -
java -verbose命令
2010-09-23 15:00 9352java -verbose[:class|gc|jni ... -
db2的jdbc驱动
2010-09-20 18:34 1227type1:jdbc-odbc桥 ... -
Java代码编写的30条建议
2010-07-21 23:28 6021) 类名首字母应该大写。字段、方法以及对象(句柄)的首字母应 ...
相关推荐
XPath 表达式比繁琐的文档对象模型(DOM)导航代码要容易编写得多。如果需要从 XML 文档中提取信息,最快捷、最简单的...Java 5 推出了 javax.xml.xpath 包,这是一个用于 XPath 文档查询的独立于 XML 对象模型的库。
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
学习核心Java语言——基本语法、类和对象以及其他的组件; 用Java进行开发,使用编译器、解释器和其他工具; 介绍Java内建的线程工具和并发包; 学习文本处理和强大的正则表达式API; 编写高级的网络化或基于Web的...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
Java网络爬虫(蜘蛛)源码项目是一个基于Java语言开发的网络爬虫工具,旨在提供一个高效、灵活的解决方案,用于从互联网上自动抓取数据。该项目利用Java的强大网络编程能力,结合多线程和网络协议理解,使得用户可以...
commons-jxpath 定义了一个简单的XPath表达式语言的解析器.JXPath应用XPath表达式来操纵各种类型的对象包括:JavaBeans,Maps,Servlet contexts,DOM等 commons-lang commons的基础包 commons-launcher 提供多平台的 ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
java.sql 提供使用 JavaTM 编程语言访问并处理存储在数据源(通常是一个关系数据库)中的数据的 API。 java.text 提供以与自然语言无关的方式来处理文本、日期、数字和消息的类和接口。 java.text.spi java.text ...
此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...
此外,本书的配套光盘还免费提供了价值人民币330元的java教学视频,对java语言进行了全面讲解,帮助一些不会java语言的读者快速地从java基础知识的学习中过渡到java web的学习与开发上. 第1部分 xml篇. 第1章 xml...
Xpath是一种易于使用的查询语言OQL与SQL类似,并提供更强大的报告功能您可以在Mendix Modeler中使用这些查询语言,但是两种语言也可以通过Java API获得。 您可以使用这些API通过连接器套件来实现功能强大且可重用的...