JDOM 使用 XPath 查找带 NameSpace 的节点

对于 XML 文件中不带命名空间(NameSpace) 的节点,如

<blog_Content>

用 JDOM 的 XPath 来搜索这个节点时可用下面之中任一代码:

①   List<Element> elements = XPath.selectNodes(document,"//blog_Content");

②   XPath xpath = XPath.newInstance("//blog_Content");
       List<Element> elements = xpath.selectNodes(document);

但是如果是查找带命名空间的节点,如

<blogns:blog_Content xmlns:blogns="x-schema:#Schema2">
    <blogns:Title>Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度</blogns:Title>
..............................................

还是用前面那两种方法可就查不到 blog_Content 节点了,即使是写成

   List<Element> elements = XPath.selectNodes(document,"//blogns:blog_Content");

或者对于 <blogns:Title> 写成

  List<Element> elements = XPath.selectNodes(document,"//blogns:Title");

都是检索不到元素的,elements.size() 为 0。

这时候,我们需要明确的指定你的 XPath 实例所要用的 NameSpace,用 XPath 的 addNamespace() 方法,操作代码如下:

      XPath xpath = XPath.newInstance("//blogns:blog_Content");
      xpath.addNamespace("blogns","x-schema:#Schema2");
      List<Element> elements = xpath.selectNodes(document);

这样就能检索到 <blogns:blog_Content> 节点了,对于 <blogns:Title> 也是一样的做法。

可是对于使用默认命名空间(Default Namespace) 的节点又该如何检索呢?例如检索下面 XML 的 <blog_Content> 节点

<blog_Content>
    <Title>Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度</Title>
.................................

以一个较为常规的思维方式吧,Default Namespace 大概就是 "" 空字符串吧,那么是不是写成

      XPath xpath = XPath.newInstance("//blog_Content");
      xpath.addNamespace("","x-schema:#Schema2");
      List<Element> elements = xpath.selectNodes(document);

就能找到节点了呢?很遗憾,这里的 elements.size() 等于 0,检索失败。

JDOM 要求,不知是否是所有 XML 解析 API 都有这样的规范,即使使用的是默认命名空间,在用 XPath 检索时也必须给这个默认命名空间指定一个名字,我们这里就选 "default" 吧,你可以任意指定一个不冲突的名字,不要被这里的 "default" 误导了只能用它。所以检索 <blog_Content> 的代码就是:

      XPath xpath = XPath.newInstance("//default:blog_Content");
      xpath.addNamespace("default","x-schema:#Schema2");
      List<Element> elements = xpath.selectNodes(document);

这样你就能检索到你要的节点了。

以上的 XML 是节选自 BlogJava 博客的日志备份数据文件(BlogJava 管理后台,点 "备份数据" 保存下来的 MyBlogData.xml)。

先告诉大家一个消息,我已经把 《Quartz Job Scheduling Framework  中文教程.chm》制作完成,很快就会拿出来与大家分享。制作这个 CHM 的方法就是从我的日志备份文件 MyBlogData.xml 中用 JDOM XPath 读出所有的 Quartz Job Scheduling Framework 翻译日志,排序,然后用模板生成一个个 HTML 文件,再用 Visual CHM 里的工程,一编译就行,只要博客上的日志内容有变,马上能生成新版的 CHM 文件。

下面附上一个列举出日志备份文件 MyBlogData.xml 中所有本站发布日志的标题的程序:

程序中用到了 XPath 实现类其实是 org.jdom.xpath.JaxenXPath,所以项目中要引用的包有:jdom.jar、saxpath.jar、jaxen-core.jar、jaxen-jdom.jar。也可以使用 XPath 的另一实现类 org.jaxen.jdom.JDOMXPath。

参考:1. XPath and Default Namespace handling(其中详细讲解了分别用 Jaxen and Dom4J,Jaxen and XOM,Jaxen and JDOM,JAXP XPathFactory,XSLT 如何处理有默认命名空间的 XML 节点)

本文链接 https://yanbin.blog/jdom-xpath-seach-namespace/, 来自 隔叶黄莺 Yanbin Blog

[版权声明] Creative Commons License 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。

Subscribe
Notify of
guest

2 Comments
Inline Feedbacks
View all comments
mohammed
16 years ago

JDOM 要求,不知是否是所有 XML 解析 API 都有这样的规范,即使使用的是默认命名空间,在用 XPath 检索时也必须给这个默认命名空间指定一个名字,我们这里就选 "default" 吧,你可以任意指定一个不冲突的名字,不要被这里的 "default" 误导了只能用它。所以检索 <blog_Content> 的代码就是:

==========================================

.Net 中的XML接口似乎也是这样,即使对于默认的XML namespace也不能直接访问到其中的节点,还是要用XmlNamespaceManager::AddNamespace()方法设置一个namespace才能读到节点

anon
14 years ago

you may want to look at vtd-xml, the latest and most advanced xml processing api

<a href="http://vtd-xml.sf.net">vtd-xml</a&gt;