클래스 이름으로 DOM 요소 가져 오기


답변:


154

업데이트 : *[@class~='my-class']CSS 선택기의 Xpath 버전

그래서 hakre의 의견에 대한 답변으로 아래의 의견을 듣고 호기심이 생겨 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_QueryCSS 선택기 구문 (jQuery)을 지원하는 것이 좋습니다 .

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

클래스 my-class2도 있지만 꽤 달콤합니다. 모든 요소 중 첫 번째 요소 만 선택하는 방법은 없나요?
hakre

xpath2 없이는 할 수 없다고 생각합니다 ... 그러나 Zend_Dom_Query의 예제는 정확히 그렇게합니다. 프로젝트에서 해당 compkenet을 사용하고 싶지 않다면 해당 CSS 선택기를 xpath로 변환하는 방법을보고 싶을 수 있습니다. DomXPath는 xpath 2.0을 지원할 수 있습니다. 확실하지 않습니다.
prodigitalson

1
때문에이 class예를 들어 하나 개 이상의 클래스를 가질 수 있습니다 <a class="my-link link-button nav-item">.
prodigitalson

2
@prodigitalson : 이것은 공백을 반영하지 않기 때문에 올바르지 않습니다. 시도해보십시오 //*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')](매우 유익한 : CSS 선택기 및 XPath 표현식 ).
hakre 2011-06-18

1
@babonk : 예, contains함께 사용해야합니다 concat... 우리는 검색하는 클래스의 양쪽에 공백을 채우거나 한쪽 만 채우는 세부 사항을 논의하고 있습니다. 그래도 작동합니다.
prodigitalson 2011-06-18

20

zend없이 클래스의 innerhtml을 얻으려면 다음을 사용할 수 있습니다.

$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'
Kamil

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
이에 대한 예는 어디에 있습니까? 좋았을 텐데.
robue-a7119895

훌륭합니다. 나는 수업과 함께 요소를 얻었습니다. 이제 클래스를 포함하는 요소에 자식을 추가하는 것과 같이 요소의 내용을 편집하고 싶습니다. 자식을 추가하고 전체 HTML을 다시 만드는 방법은 무엇입니까? 도와주세요. 이것이 내가 한 일입니다. $classResult = getElementByClass($dom, 'div', 'm-signature-pad'); $classResult->nodeValue = ''; $enode = $dom->createElement('img'); $enode->setAttribute('src', $signatureImage); $classResult->appendChild($enode);
Keyur 2011

1
php에 의한 DOM 수정의 경우 phpquery github.com/punkave/phpQuery
dav

7

를 사용하지 않고 다른 방법도 있습니다 DomXPath또는 Zend_Dom_Query.

dav의 원래 함수를 기반으로 태그와 클래스가 매개 변수와 일치하는 부모 노드의 모든 자식을 반환하는 다음 함수를 작성했습니다.

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;

다른 사람에게도 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.