xml 具有可变多条件的 XPath 查询
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8576651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XPath query with variable multiple conditions
提问by swornabsent
Long-time listener, first-time caller. I'm relatively new to XPath and looked at several other threads here and elsewhere but I can't seem to get a query working, any help would be great.
长期聆听者,初次来电者。我对 XPath 比较陌生,并在此处和其他地方查看了其他几个线程,但我似乎无法使查询正常工作,任何帮助都会很棒。
I have XML as follows:
我有如下 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 is the root element, and in this example there are no <contributor>elements)
(catalog 是根元素,在这个例子中没有<contributor>元素)
I have the query working on author, contributor, title, and language searches, but I am getting hung up on adding a file type condition. This query to find books with author OR contributor containing "Dostoyevsky" and title containing "Brothers" with language "en" is working(i.e. giving expected results), but if there's a better way to write it I'm all ears:
我有关于作者、贡献者、标题和语言搜索的查询,但我在添加文件类型条件时遇到了麻烦。此查询用于查找作者或贡献者包含“陀思妥耶夫斯基”和标题包含“兄弟”且语言为“en”的书籍正在工作(即给出预期结果),但如果有更好的编写方式,我会全力以赴:
/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en']
What I can'tget to work is limiting the query results to files of a certain type, i.e. appending and ../file/type='PDF'or something. Didn't have any luck with |unions either.
我无法开始工作的是将查询结果限制为某种类型的文件,即附加and ../file/type='PDF'或其他内容。|工会也没有运气。
Thanks in advance.
提前致谢。
Oh, and if it matters, the query needs to be built dynamically (from form input), so it needs to retain a universal syntax that would work with any number of user-supplied criteria.
哦,如果重要的话,查询需要动态构建(从表单输入),所以它需要保留一个通用语法,可以与任意数量的用户提供的条件一起使用。
回答by Vincent Biragnet
If I get you right, this should work :
如果我猜对了,这应该有效:
/catalog[file/type='PDF']//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en']
Note that the filter is directly on the catalogelement.
请注意,过滤器直接位于catalog元素上。
If you try to get bookelements, maybe you should use /catalog[file/type=...]//book[test1][test2][test3]...with your different constraints. Each new test act as a filter.
如果您尝试获取book元素,也许您应该使用/catalog[file/type=...]//book[test1][test2][test3]...不同的约束。每个新测试都充当过滤器。
回答by Dimitre Novatchev
This query to find books with author OR contributor containing "Dostoyevsky" and title containing "Brothers" with language "en" is working (i.e. giving expected results), but if there's a better way to write it I'm all ears:
/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) andcontains(../title,'Brothers') and ../@lang = 'en']
此查询查找作者或贡献者包含“陀思妥耶夫斯基”和标题包含“兄弟”且语言为“en”的书籍正在工作(即给出预期结果),但如果有更好的编写方式,我会全力以赴:
/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) andcontains(../title,'Brothers') 和 ../@lang = 'en']
The XPath expression above is not only quite imperfect and absolutely un-formatted and unreadable, but, more importantly, it doesn't (as stated) select any bookelement at all (it may select an author). Also, the //pseudo-operator isn't necessary and may significantly reduce the efficiency of XPath evaluation on any real world moderate to large XML document.
上面的 XPath 表达式不仅非常不完美,而且完全没有格式化和不可读,而且更重要的是,它根本(如所述)根本不选择任何book元素(它可能会选择一个author)。此外,//伪运算符不是必需的,并且可能会显着降低对任何现实世界中到大型 XML 文档的 XPath 评估效率。
Here is an XPath expression that selects what you want:
这是一个选择你想要的 XPath 表达式:
/catalog/book
[@lang='en'
and
file/type='PDF'
and
*[self::author
or
self::contributor
]
[contains(., 'Dostoyevsky')]
and
contains(title, 'Brothers')
]
Oh, and if it matters, the query needs to be built dynamically (from form input), so it needs to retain a universal syntax that would work with any number of user-supplied criteria.
哦,如果重要的话,查询需要动态构建(从表单输入),所以它需要保留一个通用语法,可以与任意数量的用户提供的条件一起使用。
This "universal syntax may look something like this:
这种“通用语法可能如下所示:
/*/book
[
contains(*[name() = $pName1], $pString1)
and
contains(*[name() = $pName2], $pString2)
. . . . . .
and
contains(*[name() = $pNameK], $pStringK)
]
where $pName1, $pName2, ..., $pNameKshould be substituted by the names of the fields the end user has specified in the search form, and
其中$pName1, $pName2, ...,$pNameK应替换为最终用户在搜索表单中指定的字段名称,并且
$pString1, $pString2, ..., $pStringKshould be substituted by the data that the user has indicated should be contained in the corresponding fields.
$pString1, $pString2, ...,$pStringK应替换为用户已指示应包含在相应字段中的数据。
回答by First Zero
A simpler way for doing this is to filter for the two/three conditions separately and join them,
一个更简单的方法是分别过滤两个/三个条件并加入它们,
<xsl:for-each select="//catalog//title[contains(., 'Dostoyevsky')] | //catalog//author[contains(., 'Brothers')]">
</xsl:for-each>
The pipe (|) will combine each result
管道 (|) 将组合每个结果

