2011-12-20 44 views
0

長時間的監聽器,首次調用者。我對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> 

(目錄是根元素,並且在這個例子中有沒有<contributor>元素)

我有查詢上作者,貢獻者,標題工作,和語言搜索,但我越來越掛上添加文件類型的條件。這個查詢找到包含「Dostoyevsky」作者或貢獻者的書籍和包含語言「en」的「Brothers」的標題是working(即給出預期的結果),但是如果有更好的方法來編寫它,

/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and contains(../title,'Brothers') and ../@lang = 'en'] 

不能去工作限制查詢結果追加and ../file/type='PDF'什麼特定類型的文件,即。與|工會沒有任何運氣。

在此先感謝。

哦,如果它很重要,查詢需要動態建立(從表單輸入),所以它需要保留一個通用的語法,可以處理任何數量的用戶提供的標準。

+0

請,做你的功課結合起來,並在最少提供真實的,格式良好且有意義的XML文檔。 – 2011-12-20 14:18:26

+0

Dimitre,你想要什麼?這是我真正的XML。我認爲內容不相關。 – swornabsent 2011-12-20 14:31:24

+0

@swornabsent:Dimitre是對的,你的XML格式不正確。您編寫lang屬性的方式不是XML。您應該更新您的問題以使其有效(例如lang =「...」)。 – 2011-12-20 14:36:26

回答

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]...以及您的不同約束條件。每個新測試都起到一個過濾器的作用

+0

感謝文森特,清除了一切。我領先於我自己。 – swornabsent 2011-12-20 14:45:56

+0

同樣的邏輯也適用於當你想測試下一個兄弟的東西,例如'...並且包含(text(),'Some text 1')和../td[4] ='某些文本......' – 2017-04-12 15:02:35

1

此查詢找到含有「兄弟」與語言「EN」作者或含有 「陀思妥耶夫斯基」貢獻者和標題的書是 工作(即給預期的結果),但如果有更好的方法來 寫它我所有的耳朵:

/catalog//book/*[(contains(self::author,'Dostoyevsky') or contains(self::contributor,'Dostoyevsky')) and 

含有(../標題, '兄弟')和../@lang = 'EN']

以上的XPath表達式,不僅相當不完美的d絕對沒有格式化且不可讀,但是更重要的是,它沒有(如上所述)選擇任何book元素(它可以選擇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,...,$pStringK應該被用戶指示的數據代替應該包含在相應的字段中

+0

謝謝Dimitre。這已經有點過時了,我最初有一些服務器端PHP邏輯根據產生的結果來定位所需的父元素。這是有幫助的,因爲你的其他答案。 – swornabsent 2011-12-20 14:45:13

+0

@swornabsent:不客氣。我只是更新了我的答案,讓你對所要求的「通用語法」有所瞭解 - 享受:) – 2011-12-20 14:58:17

1

這樣做更簡單的方法是分別篩選兩/三個條件,並加入他們的行列,

<xsl:for-each select="//catalog//title[contains(., 'Dostoyevsky')] | //catalog//author[contains(., 'Brothers')]"> 

</xsl:for-each> 

管道(|)將每個結果