【0】README
0.1)本文文字描述转自 core java volume 2 , 旨在理解 XML——使用 XPath来定位信息+使用命名空间 的基础知识 ;
0.2) for detailed XPath info : please visit ( http://www.ruanyifeng.com/blog/2009/07/xpath_path_expressions.html + http://www.w3schools.com/xsl/xpath_syntax.asp)
0.3) for source code about XPath,please visit https://github.com/pacosonTang/core-java-volume/tree/master/coreJavaAdvanced/chapter2/XPath
【1】XPath 相关
1)problem+solution (干货——XPath引入的原因)
- 1.1)problem: 如果要定位某个 XML 文档中的一段特定信息, 那么,通过遍历DOM 树的众多节点来进行查找显得有些麻烦;
- 1.2)solution: XPath 语言使得 访问树节点变得很容易;
2)看个荔枝:有下面的XML文档
<configuration>
<database>
<username>dbuser</username>
<password>dbuser</password>
.....
</database>
</configuration>
- 2.1)可以通过 读 XPath 表达式 /configuration/database/username 求值得到 database 中 的username;
- 2.2)使用 XPath 执行以下操作比普通的DOM 方式要简单得多:
2.3)XPath 可以描述 XML 文档中的一个节点集: 如 /a/b ;
- 2.3.1)我们可以用[] 操作符来选择特定元素:/a/b[1];
- 2.3.2)使用 @ 操作符可以得到属性值, /a/b/c@anchor
3)Java SE 5 增加了一个API来计算XPath表达式, 需要先从 XPathFactory 创建一个 XPath对象:
XPathFactory xpf = XPathFactory.newInstance();
path = xpf.newXPath();
String username = path.evaluate("/a/b/c",doc);
- 3.2)可以用同样的 XPath 对象来计算多个表达式: 这种形式的 evaluate 返回一个字符串, 这很适合用来获取文本,比如前面 的例子中的 username 节点中的文本;
- 3.3)如果XPath 表达式产生了一组节点, 请做如下调用:
NodeList nodes = (NodeList) path.evaluate("/a/b",doc,XpathConstants.NODESET);
- 3.4)如果结果只有一个节点, 则以 XPathConstants.NODE 代替:
Node node = (Node) path.evaluate("/a/b[1]",XPathConstants.NODE);
- 3.5)如果结果是一个数字, 则使用 XPathConstants.NUMBER:
int count = (Number) path.evaluate("count(/a/b)",XPathConstants.NUMBER.intValue());
- 3.6)不必从文档的根节点开始搜索, 可以从任意一个节点或节点列表开始。
如果你有前一次计算得到的节点, 那么就可以调用: result = path.evaluate(expr,node);
【2】使用命名空间
1)java用包来避免名字冲突,XML 也有类似的命名空间机制,可以用于元素名和属性名; (干货——XML的命名空间机制等同于java中的package)
- 1.1)名字空间:是由统一资源标识符(Uniform Resource Identifier, URI)来标识的;
- 1.2)HTTP的URL格式是最常用的: 注意 URL 只用作标识符字符串,而不是一个文件的定位符; (干货——HTTP的URL格式是最常用作为命名空间的,仅仅在于标识,而不是定位某个文件) 如, 名字空间标识符:
http:// www.horstman.com/corejava ; http:// www.horstman.com/corejava/index.html;表示了不同的命名空间, 尽管web 服务器为这两个URL 提供相同的文档;
2)人们习惯于将解释该命名空间的文档放在 URL位置上。如,如果你把浏览器指向 XML Schema 的命名空间URL, 你就会发现一个描述XML Schema 标准的文档;
- 2.1)为什么要用URL 作为命名空间的标识符呢? 这是因为这样容易确保它们是独一无二 的。
3)java中,使用import来指定很长的包名, 然后只需要使用较短类名;
- 3.1)在XML中,有类似机制, 如 (干货——如何在xml中引入 命名空间)
<element xmlns="namespaceURI">
children
</element>
- 3.2)现在, 该元素和他的子元素都是给定命名空间的一部分了, 子元素可以提供自己的命名空间, 如: (干货——父元素和子元素可以有自己不同的命名空间)
<element xmlns="namespaceURI1">
<child xmlns="namespaceURI2">
grandchildren
</child>
</element>
这样,第一个子元素和孙元素都是第二个命名空间的一部分了;
- 3.3)你也可以用一个前缀来表示命名空间, 即为特定文档选取的一个短的标识符。下面是一个典型的荔枝: (干货——用一个前缀来表示命名空间)
<xsd: schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd: element name="a" type="GridBagType">
</xsd: schema>
3.4)下面的属性: xmlns :prefix = “namespaceURI” , 用于定义命名空间和前缀。 在我们的例子中, 前缀是xsd。 这样, xsd:schema 实际上指的是 命名空间 http://www.w3.org/2001/XMLSchema 中的schema;
Attention)
4)默认情况下, DOM 解析器并非“命名空间感知的”, 要打开命名空间处理特性:
请调用 DocumentBuilderFactory 类的 setNamespace Aware 方法: factory.setNamespaceAware(true);
(干货——开命名空间处理特性,factory.setNamespaceAware(true))
4)看个荔枝:
- 4.1)下面是一个荔枝, 假设解析器看到了以下元素:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- 4.2) 它会报告:
限定名 = xsd :schema ;
命名空间 URI = http://www.w3.org/2001/XMLSchema ;
本地名=schema ;