2015-08-27 3 views
0

У меня есть файл HTML с дорожками в списке. Я хочу создать объект PHP для каждого трека и сохранить все объекты в PHP-массиве.Как я могу получить элементы и дочерние элементы из HTML по имени класса с помощью PHP?

HTML DOM в моем файле test.html:

<ul> 
    <li class="track"> 
     <span id="primary-info"> 
      <span class="interpret">Lorem ipsum</span> 
      <span class="title">dolor sit amet</span> 
     </span> 
     <span class="secondary-info"> 
      <span class="playtime">6:00</span> 
      <span class="label">consetetur</span> 
     </span> 
    </li> 

    <li class="track"> 
     <span id="primary-info"> 
      <span class="interpret">sed diam</span> 
      <span class="title">nonumy eirmod</span> 
     </span> 
     <span class="secondary-info"> 
      <span class="playtime">7:00</span> 
      <span class="label">invidunt</span> 
     </span> 
    </li> 

</ul> 

Мой PHP код:

<?php 

    $lTracklistArr = []; 

    // get the html 
    $HTML = file_get_contents("http://localhost/test.html"); 

    // load the dom 
    $lDoc = new DOMDocument(); 
    $lDoc->loadHTML($HTML); 

    // create XPath obj 
    $XPath = new DOMXPath($lDoc); 

    // get all tracks 
    $lTracks = $XPath->query("//*[@class='track']"); 

    $i = 0; 
    while($lTracks->item($i)) 
    { 
     // How can I get the values from the sub-elements from the DOM? 
     $lInterpret = $lTracks->item($i)-> ? 
     $lTitle = $lTracks->item($i)-> ? 
     $lPlaytime = $lTracks->item($i)-> ? 
     $lLabel = $lTracks->item($i)-> ? 

     $lTracklistArr[] = new Track($lInterpret, $lTitle, $lPlaytime, $lLabel); 

     $i++; 
    } 

    // show tracklist 
    print_r($lTracklistArr); 

    // PHP class about one track 
    Class Track 
    { 
     var $m_Interpret; 
     var $m_Title; 
     var $m_Playtime; 
     var $m_Label; 

     public function __construct($pInterpret, $pTitle, $pPlaytime, $pLabel) 
     { 
      $m_Interpret = $pInterpret; 
      $m_Title = $pTitle; 
      $m_Playtime = $pPlaytime; 
      $m_Label = $pLabel; 
     } 
    } 
?> 

Это не проблема, чтобы получить треки. Но я не могу получить значения из подэлементов по имени класса.

ПРИМЕЧАНИЕ: порядок DOM в дорожке может измениться. Необходимо получить элементы по имени класса.

ответ

0

я могу использовать XPath на дорожку, когда я конвертировать DOMElement каждого трека в HTML и конвертировать HTML снова в DOMXPath:

$lTracklistArr = []; 

// get the html 
$HTML = file_get_contents("http://localhost/test.html"); 

$XPath = GetXPathByHTML($HTML); 

// get all tracks 
$lTracks = $XPath->query("//*[@class='track']"); 

$i = 0; 
while($lTracks->item($i)) 
{    
    //save DOMElement of the Track as HTML and Convert it back into DOMXPath 
    $XPathTrack = GetXPathByHTML($lTracks->item($i)->ownerDocument->saveHTML($lTracks->item($i))); 

    // How can I get the values from the sub-elements from the DOM? 
    $lInterpret = $XPathTrack->query("//*[@class='interpret']")->item(0)->nodeValue; 
    $lTitle = $XPathTrack->query("//*[@class='title']")->item(0)->nodeValue; 
    $lPlaytime = $XPathTrack->query("//*[@class='playtime']")->item(0)->nodeValue; 
    $lLabel = $XPathTrack->query("//*[@class='label']")->item(0)->nodeValue; 

    $lTracklistArr[] = new Track($lInterpret, $lTitle, $lPlaytime, $lLabel); 

    $i++; 
} 

function GetXPathByHTML($pHTML) 
{ 
    // load the dom 
    $lDoc = new DOMDocument(); 
    libxml_use_internal_errors(true); // suppress warnings 
    $lDoc->loadHTML($pHTML); 

    // create XPath obj 
    return new DOMXPath($lDoc); 
} 

Это работает для меня. print_r($lTracklistArr) показывает результаты правильно:

Array ([0] => Track Object ([m_Interpret] => Lorem ipsum [m_Title] => dolor sit amet [m_Playtime] => 6:00 [m_Label] => consetetur) [1] => Track Object ([m_Interpret] => sed diam [m_Title] => nonumy eirmod [m_Playtime] => 7:00 [m_Label] => invidunt)) 
0

вы можете сделать это с SimpleXML:

<?php 


$lTracklistArr = []; 

// get the html 
$HTML = file_get_contents("http://localhost/test.html"); 


$classes = ["interpret", "title", "playtime", "label"]; 


$data = simplexml_load_string($HTML); 


foreach ($data->li as $e) { 

    $data = []; 

    $attr = (array) $e->attributes(); 

    if ( !isset($attr["@attributes"]["class"]) 
     || ("track" !== $attr["@attributes"]["class"]) 
    ) { 
     continue; 
    } 


    foreach ($e->span as $e2) { 
     foreach ($e2->span as $e3) { 
      $attr = (array) $e3->attributes(); 

      if (!isset($attr["@attributes"]["class"])) { 
       continue; 
      } 

      $class = $attr["@attributes"]["class"]; 

      if (!in_array($class, $classes)) { 
       continue; 
      } 

      $data[$class] = (string) $e3; 
     } 
    } 

    $lTracklistArr[] = new Track($data["interpret"], $data["title"], $data["playtime"], $data["label"]); 

} 


// show tracklist 
var_dump($lTracklistArr); 

// PHP class about one track 
Class Track 
{ 
    var $m_Interpret; 
    var $m_Title; 
    var $m_Playtime; 
    var $m_Label; 

    public function __construct($pInterpret, $pTitle, $pPlaytime, $pLabel) 
    { 
     $this->m_Interpret = $pInterpret; 
     $this->m_Title = $pTitle; 
     $this->m_Playtime = $pPlaytime; 
     $this->m_Label = $pLabel; 
    } 
} 
+0

Большое спасибо за ваши усилия. DOM из HTML-документа (в моем вопросе я только разместил необходимый html-код). Поэтому вы не можете использовать SimpleXML для этого. Функция 'simplexml_load_string' бросает несколько предупреждений и заканчивается в« Уведомлении: попытка получить свойство не-объекта »при использовании' $ data-> li' в цикле. – Simon

+0

, если вы не можете напрямую получить данные за HTML, вы можете попробовать regex – mmm