0

我正在尝试在 Linux 中使用命令行工具学习 XPath 查询(我正在学习斯坦福的 Class2Go 课程数据库简介)。给定一个名为 BookstoreQ.xml的 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

为什么?

更新:

感谢 Francis 和 Michael 帮助我理解这个问题。在 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"
4

1 回答 1

1

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

在 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 的联合运算符只能将两个节点集统一为另一个节点集,因此它必须在“最外层”表达式上下文中,而不是在路径分隔符之前或之后。

于 2013-02-21T06:16:06.173 回答