ฉันจะใช้ 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 นี้ เช่น ฉันป้อน "hello moning" ในพื้นที่ข้อความค้นหา และผลการค้นหาสามารถค้นหาองค์ประกอบวิดีโอที่มีรหัส "1"

ฉันเดาว่าการใช้ php xpath สามารถค้นหาคำหลักเพียงคำเดียวในไฟล์ xml และจะต้องวนซ้ำทั่วทั้งแผนผัง ฉันไม่มั่นใจว่าจะสามารถเขียนฟังก์ชันที่มีประสิทธิภาพดีได้

ฉันพยายามใช้แหล่งข้อมูลภายนอก เช่น Google Custom Search เพื่อค้นหาเว็บของฉัน แต่ปรากฏว่าฉันไม่ได้ใช้หน้าเว็บเพื่อแสดงวิดีโอแต่ละรายการ ฉันส่งรหัสวิดีโออื่นเป็นพารามิเตอร์ไปยังหน้าเล่นวิดีโอ

ฉันยังนึกถึงนิพจน์ทั่วไปด้วย แต่ไม่รู้ว่าจะจัดการลำดับคำหลักอย่างไร

มีเครื่องมือค้นหาใดบ้างที่ฉันสามารถใช้ค้นหาคำหลักหลายคำเพื่อระบุวิดีโอได้ ฉันออกแบบสิ่งนี้เพื่อช่วยให้ผู้ใช้ของฉันค้นหาวิดีโอที่ดูได้อย่างรวดเร็ว

ฉัน google มาก มันช้ามาก บางครั้งฉันก็เข้า google ไม่ได้ แทนฉันที่จีนที่นี่ ฉันลองใช้ "การค้นหาคำหลักหลายคำ xml" เพื่อค้นหาคำหลัก บางทีภาษาอังกฤษของฉันอาจไม่ฉลาดพอที่จะให้ Google เข้าใจความตั้งใจของฉันได้ ฉันหวังว่าพวกคุณจะเข้าใจคำถามของฉัน

ขอบคุณมาก!!


person Luke Chen    schedule 18.12.2013    source แหล่งที่มา
comment
ขอบคุณ! @Nouphal.M. ฉันประมาทมาก ไม่ได้ตรวจสอบแท็ก xml ของฉัน แต่ไม่ต้องกังวล ในโปรเจ็กต์ของฉัน แท็กทั้งหมดใช้ได้   -  person Luke Chen    schedule 19.12.2013
comment
ไม่เกี่ยวข้อง แต่ที่นี่คุณมีแนวทางที่ไม่ยุ่งยาก: fsockopen.com/php-programming/   -  person Chris Russo    schedule 17.08.2016


คำตอบ (3)


โปรดดูโค้ดตัวอย่างของฉันด้านล่างเกี่ยวกับวิธีการทำให้สำเร็จ

<?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);
}

-- แก้ไข

ฉันอ่านโพสต์ของคุณอีกครั้งและดูเหมือนว่าคุณกำลังใช้คำหลักไม่ใช่สตริง หากเป็นเช่นนั้น ให้ลองใช้ตัวอย่างนี้เพื่อดูขนาด:

<?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);
}
person Kyle    schedule 18.12.2013
comment
สวัสดี @ไคล์! ขอบคุณมาก! ฉันทดสอบโค้ดของคุณใน php sandbox มันทำงานได้ดีจริงๆ! ฉันใช้เวลาหนึ่งชั่วโมงเพื่อศึกษาฟังก์ชันบางอย่างที่ฉันไม่รู้จัก ขอบคุณ! ฉันขอถามได้ไหมว่าฟังก์ชันนี้จะส่งผลต่อประสิทธิภาพของเซิร์ฟเวอร์โฮสติ้ง php ของฉันอย่างไร สมมติว่าฉันมีผู้ใช้ 1,000 รายและ 1,000 ‹วิดีโอ› และพวกเขาค้นหาด้วยฟังก์ชันนี้ มันจะทำให้เซิร์ฟเวอร์ของฉันช้าจริง ๆ หรือไม่? ฉันไม่มีความคิดเกี่ยวกับประสิทธิภาพเลย บางทีฉันอาจดูถูกดูแคลนโฮสติ้งเซิร์ฟเวอร์ php ของฉัน? ขอบคุณ! - person Luke Chen; 19.12.2013
comment
สวัสดี @ไคล์! คุณช่วยสอนฉันหน่อยได้ไหมว่าจุด '.' ในฟังก์ชัน contrains() หมายถึงอะไร ฉันค้นหาคู่มือแล้ว มันควรจะเป็น str ที่มีคำสำคัญหรือไม่? - person Luke Chen; 19.12.2013
comment
คำถามอื่นคือฉันโหลดไฟล์ xml ฉันจะใช้ตัวพิมพ์เล็กทั้งไฟล์ xml ได้อย่างไร ฉันควรโหลด xml ก่อน แล้วจึงโหลด $dom-›saveXML($dom) หรือไม่ ขอบคุณ!! - person Luke Chen; 19.12.2013
comment
ประสิทธิภาพไม่ควรเป็นเรื่องใหญ่ หากคุณกังวล ทำไมไม่เพิ่มวิดีโอ 1,000 รายการแล้วใช้แอปพลิเคชันเพื่อเข้าถึงเซิร์ฟเวอร์ของคุณหลายครั้ง '.' ย่อมาจากโหนดปัจจุบัน คุณสามารถหาข้อมูลเพิ่มเติมได้ที่นี่: (w3schools.com/xpath/xpath_syntax.asp ). สำหรับการลดขนาดไฟล์ xml ทั้งหมด คุณสามารถทำได้ทันที (ดังที่แสดงในตัวอย่างของฉัน) หรือคุณสามารถดำเนินการด้วยตนเองกับไฟล์ก่อนที่จะอัปโหลดไปยังเซิร์ฟเวอร์ของคุณ - person Kyle; 19.12.2013
comment
ขอบคุณ! @Kyle คุณช่วยฉันจริงๆ! - person Luke Chen; 20.12.2013

ก่อนอื่น xml ของคุณยุ่ง แท็กเปิดและปิดต้องตรงกัน คุณสามารถใช้ 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);

คุณสามารถดูการสาธิตการทำงานได้ที่นี่

person Nouphal.M    schedule 18.12.2013
comment
ขอบคุณมาก! @ Nouphal.M และขอบคุณสำหรับ php sandbox ที่ยอดเยี่ยม ฉันไม่เคยรู้มาก่อน! ขออภัยไม่สามารถยอมรับสองคำตอบได้ แต่ Kyle ช่วยฉันระบุรหัสวิดีโอโดยการค้นหาคำหลักทั้งใน cnSub และ enSub - person Luke Chen; 19.12.2013

ฉันเดาว่าคุณสามารถใช้เซิร์ฟเวอร์การค้นหาเช่น ElasticSearch ได้ มันใช้ Lucene เพื่อจัดทำดัชนีเนื้อหาทุกประเภท เนื้อหาที่จัดทำดัชนีแล้วสามารถสืบค้นผ่าน JSON API

แน่นอนว่าสิ่งนี้จะสมเหตุสมผลก็ต่อเมื่อคุณทำงานกับข้อมูลจำนวนมากอย่างต่อเนื่อง

อีกวิธีหนึ่งคือแยกวิเคราะห์ xml และสร้างอาร์เรย์ซึ่งมีแต่ละคำในแท็กย่อยเป็นดัชนี จากนั้นค่าจะเป็นอาร์เรย์ที่มีรหัสของภาพยนตร์ซึ่งมีคำนั้นอยู่ในแท็กที่เกี่ยวข้อง โดยพื้นฐานแล้วคุณกำลังสร้างดัชนีข้อมูลอย่างง่ายของคุณเอง

จากนั้นคุณสามารถค้นหาดัชนีของคุณดังนี้:

<?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 เพียงครั้งเดียวในขณะที่ค้นหาได้ค่อนข้างรวดเร็ว BTW - หากคุณต้องการใช้คำค้นหาด้วย OR แทน AND คุณสามารถใช้ array_merge และ array_unique แทน array_intersect

ตรงกลางจะเป็นแนวทางในการตั้งค่าฐานข้อมูลจริง เช่น MySQL และทำการค้นหาข้างต้นในแบบสอบถาม .

มันขึ้นอยู่กับสิ่งที่คุณต้องการทำให้สำเร็จ

person Christoph Grimmer-Dietrich    schedule 18.12.2013
comment
ขอบคุณ! @คริสตอฟ กริมเมอร์-ดีทริช ขออภัย ฉันยังใหม่กับ php และ xml ไม่เคยใช้ดัชนีมาก่อน และคำตอบของ Kyle ก็สามารถทำได้แล้ว และฉันสามารถเข้าใจรหัสของเขาได้ ขอบคุณทุกคนเหมือนกัน! - person Luke Chen; 19.12.2013
comment
ไม่มีปัญหา @LukeChen อาจมีคนอื่นพบว่าคำตอบของฉันมีประโยชน์ เนื่องจาก SO มีผู้คนมากมายมาเยี่ยมเยียน มันอาจจะไม่ใช่เรื่องไร้สาระ :-) - person Christoph Grimmer-Dietrich; 23.12.2013