PHP DOM kullanıyorum ve belirli bir sınıf adına sahip bir DOM düğümü içinde bir öğe almaya çalışıyorum. Bu alt öğeyi almanın en iyi yolu nedir?
Güncelleme:Mechanize
Çalışması çok daha kolay olan PHP için kullanmayı bıraktım .
PHP DOM kullanıyorum ve belirli bir sınıf adına sahip bir DOM düğümü içinde bir öğe almaya çalışıyorum. Bu alt öğeyi almanın en iyi yolu nedir?
Güncelleme:Mechanize
Çalışması çok daha kolay olan PHP için kullanmayı bıraktım .
Yanıtlar:
Güncelleme: *[@class~='my-class']
css seçicinin Xpath sürümü
Hakre'nin yorumuna cevaben aşağıdaki yorumumdan sonra, merak ettim ve arkasındaki kodu inceledim Zend_Dom_Query
. Yukarıdaki seçici aşağıdaki xpath için derlenmiş gibi görünüyor (test edilmemiş):
[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]
yani php şöyle olacaktır:
$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");
Temel olarak, burada yaptığımız class
tek şey, tek bir sınıf bile boşluklarla sınırlanacak ve tüm sınıf listesi boşluklarla sınırlanacak şekilde niteliği normalize etmektir . Ardından aradığımız sınıfı bir boşlukla ekleyin. Bu şekilde etkin bir şekilde sadece örneklerini arıyoruz ve buluyoruz my-class
.
Bir xpath seçici mi kullanıyorsunuz?
$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(@class, '$classname')]");
Yalnızca tek tür bir öğe *
ise, belirli bir etiket adı ile değiştirebilirsiniz .
Bunu çok karmaşık seçici ile yapmanız gerekiyorsa Zend_Dom_Query
, CSS seçici sözdizimini (a la jQuery) destekleyen hangisini öneririm :
$finder = new Zend_Dom_Query($html);
$classname = 'my-class';
$nodes = $finder->query("*[class~=\"$classname\"]");
my-class2
da bulur , ancak oldukça tatlıdır. Tüm öğelerden yalnızca ilkini seçmenin bir yolu var mı?
class
örneğin birden fazla sınıf sahip olabilir: <a class="my-link link-button nav-item">
.
//*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')]
(Çok bilgilendirici: CSS Seçiciler ve XPath İfadeleri ).
contains
ile birlikte concat
... biz jsut için sınıf sen arama her iki tarafındaki boşluk doldurma veya sadece bir tarafını doldurma ettiği durumların görüşüyorlar. Her ikisi de çalışmalı.
Sınıfın içhtml'sini zend olmadan almak isterseniz, bunu kullanabilirsiniz:
$dom = new DomDocument();
$dom->load($filePath);
$classname = 'main-article';
$finder = new DomXPath($dom);
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");
$tmp_dom = new DOMDocument();
foreach ($nodes as $node)
{
$tmp_dom->appendChild($tmp_dom->importNode($node,true));
}
$innerHTML.=trim($tmp_dom->saveHTML());
echo $innerHTML;
$classname = 'main-article'
Kabul edilen yolun daha iyi olduğunu düşünüyorum, ancak bu da işe yarayabilir
function getElementByClass(&$parentNode, $tagName, $className, $offset = 0) {
$response = false;
$childNodeList = $parentNode->getElementsByTagName($tagName);
$tagCount = 0;
for ($i = 0; $i < $childNodeList->length; $i++) {
$temp = $childNodeList->item($i);
if (stripos($temp->getAttribute('class'), $className) !== false) {
if ($tagCount == $offset) {
$response = $temp;
break;
}
$tagCount++;
}
}
return $response;
}
$classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
DomXPath
Veya kullanmadan başka bir yaklaşım daha var Zend_Dom_Query
.
Dav'ın orijinal işlevine dayanarak, etiketi ve sınıfı parametrelerle eşleşen ana düğümün tüm alt öğelerini döndüren aşağıdaki işlevi yazdım.
function getElementsByClass(&$parentNode, $tagName, $className) {
$nodes=array();
$childNodeList = $parentNode->getElementsByTagName($tagName);
for ($i = 0; $i < $childNodeList->length; $i++) {
$temp = $childNodeList->item($i);
if (stripos($temp->getAttribute('class'), $className) !== false) {
$nodes[]=$temp;
}
}
return $nodes;
}
$html
aşağıdaki HTML'ye sahip bir değişkeniniz olduğunu varsayalım :
<html>
<body>
<div id="content_node">
<p class="a">I am in the content node.</p>
<p class="a">I am in the content node.</p>
<p class="a">I am in the content node.</p>
</div>
<div id="footer_node">
<p class="a">I am in the footer node.</p>
</div>
</body>
</html>
kullanımı getElementsByClass
şu kadar basittir:
$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadHTML($html);
$content_node=$dom->getElementById("content_node");
$div_a_class_nodes=getElementsByClass($content_node, 'div', 'a');//will contain the three nodes under "content_node".
DOMDocument yazması yavaş ve phpQuery'de bozuk bellek sızıntısı sorunları var. Kullanmaya son verdim:
https://github.com/wasinger/htmlpagedom
Bir sınıf seçmek için:
include 'includes/simple_html_dom.php';
$doc = str_get_html($html);
$href = $doc->find('.lastPage')[0]->href;
Umarım bu başka birine de yardımcı olur