长期听众,第一次来电。我对XPath比较陌生,在这里和其他地方看了几个其他线程,但我似乎无法查询,任何帮助都会很棒。
我的XML如下:
<catalog>
<book pgid="28054" lang="en">
<title>The Brothers Karamazov</title>
<author>Dostoyevsky, Fyodor</author>
<friendly_title>The Brothers Karamazov by Fyodor Dostoyevsky</friendly_title>
<file>
<type>ePub</type>
<path>cache/generated/28054/</path>
<name>pg28054.epub</name>
<size>800</size>
</file>
<file>
<type>PDF</type>
<path>2/8/0/5/28054/</path>
<name>28054-pdf.pdf</name>
<size>5829</size>
</file>
<file>
<type compression="zipped">PDF</type>
<path>2/8/0/5/28054/</path>
<name>28054-pdf.zip</name>
<size>1693</size>
</file>
<file>
<type encoding="utf-8" compression="zipped">Text</type>
<path>2/8/0/5/28054/</path>
<name>28054-0.zip</name>
<size>726</size>
</file>
</book>
</catalog>
(catalog是根元素,在本例中没有<contributor>
个元素)
我有查询处理作者,撰稿人,标题和语言搜索,但我在添加文件类型条件时感到困惑。查找包含“Dostoyevsky”的作者或撰稿人以及包含“兄弟”并且语言为“en”的标题的查询是正在工作(即给出预期结果),但是如果有更好的方法来编写它我全是耳朵:
/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en']
我无法开始工作的是将查询结果限制为某种类型的文件,即附加and ../file/type='PDF'
或其他内容。与|
工会没有任何运气。
提前致谢。
哦,如果重要的话,需要动态构建查询(来自表单输入),因此需要保留一个通用语法,该语法可以使用任意数量的用户提供的标准。
答案 0 :(得分:3)
如果我找对你,这应该有效:
/catalog[file/type='PDF']//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en']
请注意,过滤器直接位于catalog
元素上。
如果您尝试获取book
元素,可能应该使用/catalog[file/type=...]//book[test1][test2][test3]...
来处理不同的约束。每个新测试都充当过滤器。
答案 1 :(得分:1)
此查询可查找包含作者或撰稿人的书籍 “陀思妥耶夫斯基”和包含语言“en”的“兄弟”的标题是 工作(即给出预期的结果),但如果有更好的方法 写下来我全都听见了:
/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and
包含(../ title,'Brothers')和../@lang ='en']
上面的XPath表达式不仅非常不完美且完全没有格式化且不可读,但更重要的是,它没有(如上所述)选择任何book
元素(它可能选择{{{ 1}})。此外,author
伪运算符不是必需的,可能会显着降低任何真实的中等到大型XML文档的XPath评估效率。
这是一个选择所需内容的XPath表达式:
//
哦,如果重要的话,需要动态构建查询(来自 表单输入),因此它需要保留一个可行的通用语法 使用任意数量的用户提供的标准。
这种“通用语法可能如下所示:
/catalog/book
[@lang='en'
and
file/type='PDF'
and
*[self::author
or
self::contributor
]
[contains(., 'Dostoyevsky')]
and
contains(title, 'Brothers')
]
其中/*/book
[
contains(*[name() = $pName1], $pString1)
and
contains(*[name() = $pName2], $pString2)
. . . . . .
and
contains(*[name() = $pNameK], $pStringK)
]
,$pName1
,...,$pName2
应替换为最终用户在搜索表单中指定的字段的名称,并且
$pNameK
,$pString1
,...,$pString2
应替换为用户指示的数据应包含在相应字段中。
答案 2 :(得分:1)
更简单的方法是分别过滤两个/三个条件并加入它们,
<xsl:for-each select="//catalog//title[contains(., 'Dostoyevsky')] | //catalog//author[contains(., 'Brothers')]">
</xsl:for-each>
管道(|)将结合每个结果