DOMname द्वारा DOM तत्व प्राप्त करना


124

मैं PHP DOM का उपयोग कर रहा हूँ और मैं एक DOM नोड के भीतर एक तत्व प्राप्त करने की कोशिश कर रहा हूँ जिसका एक दिया गया वर्ग नाम है। उस उप-तत्व को प्राप्त करने का सबसे अच्छा तरीका क्या है?

अद्यतन: मैंने MechanizePHP के लिए उपयोग करना समाप्त कर दिया है , जिसके साथ काम करना बहुत आसान था।


जवाबों:


154

अद्यतन: *[@class~='my-class']सीएसएस चयनकर्ता का Xpath संस्करण

तो हैकर की टिप्पणी के जवाब में नीचे मेरी टिप्पणी के बाद, मैं उत्सुक हो गया और पीछे के कोड में देखा Zend_Dom_Query। ऐसा लगता है कि उपरोक्त चयनकर्ता को निम्नलिखित xpath (अप्रयुक्त) में संकलित किया गया है:

[contains(concat(' ', normalize-space(@class), ' '), ' my-class ')]

तो php होगा:

$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]");

मूल रूप से, हम सभी यहां classविशेषता को सामान्य करते हैं ताकि एक भी वर्ग रिक्त स्थान से घिरा हो, और पूर्ण वर्ग सूची रिक्त स्थान में बंधी हो। फिर उस कक्षा को जोड़ दें जिसे हम एक स्थान के साथ खोज रहे हैं। इस तरह हम प्रभावी रूप से देख रहे हैं और केवल उदाहरणों को ढूंढते हैं my-class


एक xpath चयनकर्ता का उपयोग करें?

$dom = new DomDocument();
$dom->load($filePath);
$finder = new DomXPath($dom);
$classname="my-class";
$nodes = $finder->query("//*[contains(@class, '$classname')]");

यदि यह केवल एक प्रकार का तत्व है तो आप इसे *विशेष टैग्नैम से बदल सकते हैं ।

अगर आपको बहुत जटिल चयनकर्ता के साथ यह करने की आवश्यकता है, तो मैं सुझाऊंगा कि Zend_Dom_Queryकौन सीएसएस चयनकर्ता सिंटैक्स (एक ला jQuery) का समर्थन करता है:

$finder = new Zend_Dom_Query($html);
$classname = 'my-class';
$nodes = $finder->query("*[class~=\"$classname\"]");

वर्ग के my-class2रूप में अच्छी तरह से पाता है , लेकिन बहुत प्यारा है। केवल सभी तत्वों में से पहला चुनने का कोई तरीका?
हकर्रे

मुझे नहीं लगता कि आप xpath2 के बिना कर सकते हैं ... हालांकि Zend_Dom_Query के लिए उदाहरण बिल्कुल यही करता है। यदि आप अपनी परियोजना में उस संकलन का उपयोग नहीं करना चाहते हैं, तो आप यह देखना चाहते हैं कि वे उस सीएसएस चयनकर्ता को xath में कैसे अनुवाद कर रहे हैं। शायद DomXPath xpath 2.0 का समर्थन करता है - इसके बारे में निश्चित नहीं है।
२१

1
क्योंकि classउदाहरण के लिए एक से अधिक वर्ग हो सकते हैं <a class="my-link link-button nav-item">:।
prodigitalson

2
@prodigitalson: यह गलत है क्योंकि यह रिक्त स्थान को प्रतिबिंबित नहीं करता है, कोशिश करें //*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')](बहुत जानकारीपूर्ण: CSS चयनकर्ता और XPath अभिव्यक्तियाँ )।
हैकर

1
@ बबोंक: हाँ, आपको इसके containsसाथ संयोजन में उपयोग करने की आवश्यकता है concat... हम वर्ग के दोनों किनारों पर रिक्त स्थान की पैडिंग के विवरण पर चर्चा कर रहे हैं। आप केवल एक पक्ष की खोज कर रहे हैं। हालांकि काम करना चाहिए।
20 अगस्त

20

यदि आप बिना zend के वर्ग के इनरहैम को प्राप्त करना चाहते हैं तो आप इसका उपयोग कर सकते हैं:

$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;

2
लाइन के लिए गुम अर्धविराम$classname = 'main-article'
कामिल

12

मुझे लगता है कि स्वीकृत तरीका बेहतर है, लेकिन मुझे लगता है कि यह भी काम कर सकता है

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

2
इसके लिए उदाहरण कहां है? अच्छा होता।
लूट-ए 7119895

एक दम बढ़िया। मुझे कक्षा के साथ तत्व मिला। अब मैं तत्व की सामग्री को संपादित करना चाहता हूं, जैसे बच्चे को कक्षा वाले तत्व में जोड़ना। बच्चे को कैसे जोड़ें और पूरे HTML को फिर से बनाएँ? कृपया मदद कीजिए। यही है जो मैने किया है। $classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Keyur

1
php द्वारा डोम संशोधन के लिए मुझे लगता है कि इसके बेहतर इस्तेमाल करने के लिए phpquery github.com/punkave/phpQuery
डीएवी

7

वहाँ भी के उपयोग के बिना एक और दृष्टिकोण है DomXPathया Zend_Dom_Query

डीएवी के मूल कार्य के आधार पर, मैंने निम्नलिखित फ़ंक्शन को लिखा, जो मूल नोड के सभी बच्चों को लौटाता है जिनके टैग और वर्ग मापदंडों से मेल खाते हैं।

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निम्न HTML का एक चर है:

<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>

उपयोग के getElementsByClassरूप में सरल है:

$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".

6

DOMDocument टाइप करने के लिए धीमा है और phpQuery में खराब मेमोरी लीक मुद्दे हैं। मैंने प्रयोग करके समाप्त किया:

https://github.com/wasinger/htmlpagedom

एक वर्ग का चयन करने के लिए:

include 'includes/simple_html_dom.php';

$doc = str_get_html($html);
$href = $doc->find('.lastPage')[0]->href;

मुझे उम्मीद है कि इससे किसी और को भी मदद मिलेगी

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.