为什么这是一个XPath无效的查询表达式,Xmllint对Saxon有效?

时间:2013-02-21 06:11:47

标签: xml xpath saxon xmllint

我正在尝试使用Linux中的命令行工具学习XPath查询(我正在学习斯坦福大学的Class2Go课程数据库简介)。给定一个名为BookstoreQ.xml的Bookstore的XML文件,其中包含Books和Magazines,我可以在命令行运行以下查询:

$ java -cp Saxon-HE-9.4.0.6.jar net.sf.saxon.Query -s:"BookstoreQ.xml" \
       -qs:'<results>{/Bookstore/(Book|Magazine)/Title}</results>'

,它将返回以下结果:

<?xml version="1.0" encoding="UTF-8"?>
<results>
  <Title>A First Course in Database Systems</Title>
  <Title>Database Systems: The Complete Book</Title>
  <Title>Hector and Jeff's Database Hints</Title>
  <Title>Jennifer's Economical Database Hints</Title>
  <Title>National Geographic</Title>
  <Title>National Geographic</Title>
  <Title>Newsweek</Title>
  <Title>Hector and Jeff's Database Hints</Title>
</results>

如果我在命令行使用xmllint,我会得到相同的结果,如下所示:

$ xmllint --xpath '/Bookstore/Book/Title | /Bookstore/Magazine/Title'

但是,如果我尝试使用与Saxon示例中相同的XPath查询,那么我会收到如下错误:

$ xmllint --xpath '/Bookstore/(Book|Magazine)/Title' BookstoreQ.xml
XPath error: Invalid Expression
/Bookstore/(Book|Magazine)/Title
           ^
xmlXPathEval: evaluation failed
XPath evaluation failure

为什么?

更新:

感谢弗朗西斯和迈克尔帮助我理解这个问题。在linux的命令行中使用XPath的解决方法是使用类似于下面脚本的东西。

#!/bin/bash
# This script to run xpath queries
java -cp Saxon-HE-9.4.0.6.jar net.sf.saxon.Query -qs:"<results>{$1}</results>" \ 
\!indent=yes
echo

它假设您已将saxon放置在Java类路径中的某个位置。因此,下面的查询将输出上述结果(正确缩进):

$ xpath.sh "doc('BookstoreQ.xml')/Bookstore/(Book|Magazine)/Title"

1 个答案:

答案 0 :(得分:1)

xmllib2(由xmllint使用)只知道XPath 1.0,它不能在路径步骤((Book|Magazine)部分)中使用union运算符。

在XPath 1.0中,您必须写(/Bookstore/Book/Title | /Bookstore/Magazine/Title)/Bookstore/*[name()='Book' or name()='Magazine']/Title

这种限制的根本原因是XPath 1.0没有序列概念,只有节点集。序列数据类型是为XPath 2和XQuery创建的。 /Bookstore/(Book|Magazine)/Title沿着每个路径步骤传递一个序列:序列与文档节点,然后是Bookstore子元素,然后Book和Magazine子元素序列的并集按文档顺序排序,然后是Title元素的子元素。 XPath 1.0的union运算符只能将两个节点集统一到另一个节点集中,因此它必须位于“最外层”表达式上下文中,而不是在路径分隔符之前或之后。