具有可变多个条件的XPath查询

时间:2011-12-20 14:04:10

标签: xml xslt xpath

长期听众,第一次来电。我对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'或其他内容。与|工会没有任何运气。

提前致谢。

哦,如果重要的话,需要动态构建查询(来自表单输入),因此需要保留一个通用语法,该语法可以使用任意数量的用户提供的标准。

3 个答案:

答案 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>

管道(|)将结合每个结果