2013-12-18 21 views
0

我有一個XML文件中像這樣,存儲視頻的字幕:如何使用php在xml文件中搜索多個關鍵詞並返回包含標籤?

<videos> 
    <video> 
     <id>1</id> 
     <enSub>Hello Foo! Good morning!</enSub> 
     <cnSub>你好 Foo! 早上好!</cnSub> 
    </video> 
    <video> 
     <id>2</id> 
     <enSub>Hello Bar! Good afternoon!</enSub> 
     <cnSub>你好 Bar! 下午好!</cnSub> 
    </video> 
</videos> 

我想通過這個XML來搜索特定的關鍵字,例如我在搜索文本區域中輸入「你好moning」,並將搜索結果可能找到ID爲「1」的視頻元素。

我想使用php xpath只能在xml文件中找到單個關鍵字,並且它必須遍歷整個樹。我不確定我能寫出性能良好的函數。

我試圖使用外部資源,如谷歌自定義搜索來搜索我的網站,但事實證明,我沒有使用網頁來顯示每個視頻。我將不同的視頻ID作爲參數傳遞給視頻播放頁面。

我也想過正則表達式,但不知道如何處理關鍵字的順序。

所以有什麼搜索引擎,我可以使用搜索多個關鍵字來查明視頻。我將其設計爲幫助我的用戶快速找到所觀看的視頻。

我搜索了很多。這真的很慢,有時我無法訪問谷歌,在我這裏的中國地方。我嘗試了「多個關鍵字搜索xml」作爲搜索關鍵字。也許我的英語不夠聰明,谷歌無法理解我的意圖。我希望你們在這裏明白我的問題。

非常感謝你!

+0

謝謝! @ Nouphal.M。我真的很粗心,沒有檢查我的XML標籤。但別擔心。在我的項目中,所有標籤都可以。 –

+0

無關,但在這裏你有一個無憂的方法:http://fsockopen.com/php-programming/your-final-stop-for-php-xpath-case-insensitive –

回答

1

請參閱下面關於如何完成此操作的示例代碼。

<?php 
$xml = <<<XML 
<videos> 
    <video> 
     <id>1</id> 
     <enSub>Hello Foo! Good morning!</enSub> 
     <cnSub>你好 Foo! 早上好!</cnSub> 
    </video> 
    <video> 
     <id>2</id> 
     <enSub>Hello Bar! Good afternoon!</enSub> 
     <cnSub>你好 Bar! 下午好!</cnSub> 
    </video> 
</videos> 
XML; 
// Lowercase the XML so we can do a non-case-sensitive search. 
$xml = strtolower($xml); 
// Create a DOMDocument based on the xml. 
$dom = new DOMDocument; 
$dom->loadXML($xml); 
// Create an xpath based on the dom document so we can search it. 
$xpath = new DOMXpath($dom); 
// Search for any video tag that contains the text good morning. 
$nodes = $xpath->query('//video[contains(.,\'good morning\')]'); 
// Iterate all nodes 
foreach($nodes as $node){ 
    // find the ID node and print its content. 
    var_dump($xpath->query('id',$node)->item(0)->textContent); 
} 

- 編輯

我重讀您的文章,它看起來像你使用的關鍵字,而不是字符串。如果是這樣的話,那就試試這個片斷尺寸爲:

所有的XML
<?php 
$xml = <<<XML 
<videos> 
    <video> 
     <id>1</id> 
     <enSub>Hello Foo! Good morning!</enSub> 
     <cnSub>你好 Foo! 早上好!</cnSub> 
    </video> 
    <video> 
     <id>2</id> 
     <enSub>Hello Bar! Good afternoon!</enSub> 
     <cnSub>你好 Bar! 下午好!</cnSub> 
    </video> 
</videos> 
XML; 
// Lowercase the XML so we can do a non-case-sensitive search. 
$xml = strtolower($xml); 
// Create an DOMDocument based on the xml. 
$dom = new DOMDocument; 
$dom->loadXML($xml); 
// Create an xpath based on the dom document so we can search it. 
$xpath = new DOMXpath($dom); 
// Define the search keywords 
$searchKeywords = array('good','hello'); 
// Iterate all of them to make them into valid xpath 
$searchKeywords = array_map(
    function($keyword){ 
     // Replace any single quotes with an escaped single quote. 
     $keyword = str_replace('\'','\\\'',$keyword); 
     return 'contains(.,\''.$keyword.'\')'; 
    }, 
    $searchKeywords 
); 
// Implode all the keywords using and, you could change this to be 
// an"or" condition if you so desire. 
$searchKeywords = implode(' and ',$searchKeywords); 
// The search keywords now look like contains(.,'good') and contains(.,'hello') 
// Search for any video tag that contains the text good morning. 
$nodes = $xpath->query('//video['.$searchKeywords.']'); 
// Iterate all nodes 
foreach($nodes as $node){ 
    // find the ID node and print its content. 
    var_dump($xpath->query('id',$node)->item(0)->textContent); 
} 
+0

嗨@Kyle!非常感謝!我在php沙箱中測試了你的代碼。它工作得很好!我花了一個小時來研究一些我不知道的功能。謝謝!我可以問這個函數如何影響我的php託管服務器的性能嗎?假設我有1000個用戶和1000個

+0

hello @Kyle!你能教我一下在contrains()函數中的點,'。'是什麼意思?我查閱了手冊,應該是包含關鍵字的str嗎? –

+0

另一個問題是,我加載了一個XML文件。我怎樣才能小寫整個XML文件?我應該首先加載xml,然後$ dom-> saveXML($ dom)?謝謝!! –

0

首先是凌亂的,開閉標籤必須匹配。您可以使用DomDOcument來操作xml。

$searchStr ="hello afternoon"; 
$searchArr = explode(" ",$searchStr); 
$result = array(); 
$xmlData = "<videos> 
    <video> 
     <id>1</id> 
     <enSub>Hello Foo! Good morning!</enSub> 
     <cnSub>你好 Foo! 早上好!</cnSub> 
    </video> 
    <video> 
     <id>2</id> 
     <enSub>Hello Bar! Good afternoon!</enSub> 
     <cnSub>你好 Bar! 下午好!</cnSub> 
    </video> 
</videos>"; 

$dom = new DOMDocument(); 
$dom->loadXML($xmlData); 
foreach ($dom->documentElement->childNodes as $node) { 
if($node->nodeType==1){ 
    $enSub = $node->getElementsByTagName('enSub')->Item(0)->nodeValue; 
    $cnSub = $node->getElementsByTagName('cnSub')->Item(0)->nodeValue; 
    $id = $node->getElementsByTagName('id')->Item(0)->nodeValue; 
    foreach($searchArr as $key=>$val){ 
     $temp = array(); 
     if(strpos($enSub,$val) != false){ 
      $temp[$id] = array(
      'id'=>$id, 
      'enSub'=>$enSub, 
      'cnSub'=>$cnSub 
     ); 
      $result[$id]=$temp; 
     } 

    } 
} 
} 
echo "<pre>"; 
print_r($result); 

您可以找到工作演示here

+0

非常感謝! @ Nouphal.M並感謝你的偉大的PHP沙箱,我從來不知道!抱歉不能接受兩個答案,但Kyle通過在cnSub和enSub中搜索關鍵詞來幫助我找出視頻ID。 –

0

我想你可以使用一個搜索服務器一樣ElasticSearch。它使用Lucene來索引任何類型的內容。索引的內容可以通過JSON API進行查詢。

這當然只有在你持續處理大量數據時纔有意義。

另一種方法是解析XML並建立一個數組,其中每個子標籤中的項都作爲索引。該值將是一個包含電影的ID的數組,這些電影的ID在其各自的標記中包含該項。 基本上你正在建立一個你自己的簡單數據索引。

然後,您可以查詢你的指數是這樣的:

<?php 

$index = array(
    'Hello' => array(1,3), 
    'World' => array(1), 
    'Good' => array(2), 
    'Morning' => array(2), 
    'Vietnam' => array(2,3), 
); 

$searchTerms = array('Hello', 'World'); 

$found = null; 
foreach($searchTerms as $term){ 
    if(array_key_exists($term, $index)){ 
     if(is_null($found)){ 
      $found = $index[$term]; 
     } else { 
      $found = array_intersect($found, $index[$term]); 
     } 
    } else { 
     $found = array(); 
     break; 
    } 
} 

print_r($found); 

這種方法的主要好處是,你將只需要一次遍歷XML文檔具有相當快速的搜索時間。順便說一句 - 如果你想用OR來代替AND,你可以使用array_merge和array_unique來代替array_intersect。

中間的某個地方可能會設置一個像MySQL這樣的真實數據庫,並在查詢中執行上述搜索。

這真的取決於你想完成什麼。

+0

謝謝! @Christoph Grimmer-Dietrich。對不起,我是新來的PHP和XML,沒有使用索引之前。凱爾的答案已經可以做到這一點。我可以理解他的代碼。謝謝你們一樣! –

+0

沒問題,@LukeChen。也許別人認爲我的答案有用。由於許多人都訪問過它,所以它可能不適合:-) –

相關問題