preg_replace에서 html 태그를 무시하십시오.
PHPpreg_replace에서 html 태그를 무시하십시오.
이 preg_replace에서 html 태그를 무시하려면 어떻게해야합니까? 검색을 위해 foreach 함수가 있으므로 누군가가 "apple span"을 검색하면 preg_replace도 span 및 html break에 범위를 적용합니다.
preg_replace("/($keyword)/i","<span class=\"search_hightlight\">$1</span>",$str);
미리 감사드립니다!
해결법
-
==============================
1.정규식을 사용하는 대신 DOMDocument 및 DOMXPath를 기반으로 함수를 작성해야한다고 가정합니다. 그것들이 꽤 강력하더라도 정규 표현식으로 해결하기가 쉽지는 않지만 항상 (항상) 쉽게 설명 할 수있는 문제와 마주하게됩니다.
정규식을 사용하는 대신 DOMDocument 및 DOMXPath를 기반으로 함수를 작성해야한다고 가정합니다. 그것들이 꽤 강력하더라도 정규 표현식으로 해결하기가 쉽지는 않지만 항상 (항상) 쉽게 설명 할 수있는 문제와 마주하게됩니다.
일반적인 말은 : HTML을 정규 표현식으로 구문 분석하지 마십시오.
모든 규칙과 마찬가지로 항상 명심해야 할 좋은 규칙이며, 항상 적용되는 것은 아니며, 그것에 대해 마음을 굳힐 가치가 있습니다.
XPath를 사용하면 모든 XML 요소를 무시하고 텍스트 내에서만 검색어가 포함 된 모든 텍스트를 찾을 수 있습니다.
그런 다음 해당 텍스트를 으로 감싸기 만하면됩니다.
편집 : 마침내 일부 코드;)
먼저 xpath를 사용하여 검색 텍스트가 포함 된 요소를 찾습니다. 내 쿼리는 다음과 같을 것입니다.이 쿼리는 더 잘 작성 될 수 있습니다. 저는 프로가 아닌 xpath 프로입니다.
'//*[contains(., "'.$search.'")]/*[FALSE = contains(., "'.$search.'")]/..'
$ search는 검색 할 텍스트를 포함하고 "(따옴표) 문자를 포함하지 않습니다 (이 경우 괄호 안에 들어 있습니다. 따옴표가 필요할 경우 xpath 속성 정리 및 sanitizing을 참조하십시오).
이 쿼리는 함께 넣어지는 textnodes를 포함하는 모든 부모를 검색 용어가 포함 된 문자열로 반환합니다.
그러한 목록은 그대로 처리하기가 쉽지 않기 때문에 DOMText 노드 목록을 나타내는 TextRange 클래스를 만들었습니다. textnodes리스트가 하나의 문자열 인 것처럼 문자열 연산을 수행하는 것이 유용합니다.
이것은 루틴의 기본 골격입니다.
$str = '...'; # some XML $search = 'text that span'; printf("Searching for: (%d) '%s'\n", strlen($search), $search); $doc = new DOMDocument; $doc->loadXML($str); $xp = new DOMXPath($doc); $anchor = $doc->getElementsByTagName('body')->item(0); if (!$anchor) { throw new Exception('Anchor element not found.'); } // search elements that contain the search-text $r = $xp->query('//*[contains(., "'.$search.'")]/*[FALSE = contains(., "'.$search.'")]/..', $anchor); if (!$r) { throw new Exception('XPath failed.'); } // process search results foreach($r as $i => $node) { $textNodes = $xp->query('.//child::text()', $node); // extract $search textnode ranges, create fitting nodes if necessary $range = new TextRange($textNodes); $ranges = array(); while(FALSE !== $start = strpos($range, $search)) { $base = $range->split($start); $range = $base->split(strlen($search)); $ranges[] = $base; }; // wrap every each matching textnode foreach($ranges as $range) { foreach($range->getNodes() as $node) { $span = $doc->createElement('span'); $span->setAttribute('class', 'search_hightlight'); $node = $node->parentNode->replaceChild($span, $node); $span->appendChild($node); } } }
내 예제 XML :
<html> <body> This is some <span>text</span> that span across a page to search in. and more text that span</body> </html>
다음 결과가 생성됩니다.
<html> <body> This is some <span><span class="search_hightlight">text</span></span><span class="search_hightlight"> that span</span> across a page to search in. and more <span class="search_hightlight">text that span</span></body> </html>
이는 심지어 여러 태그에 분산 된 텍스트를 찾을 수 있음을 보여줍니다. 그것은 정규 표현식으로는 그렇게 쉽게 가능하지 않습니다.
여기서 전체 코드를 찾으십시오 : http://codepad.viper-7.com/U4bxbe (Answer 예제에서 가져온 TextRange 클래스 포함).
사이트가 사용하고있는 오래된 LIBXML 버전 때문에 바이퍼 코드 패드에서 제대로 작동하지 않습니다. 그것은 내 LIBXML 버전 20707 잘 작동합니다.이 문제에 대한 관련 질문을 만들었습니다 : XPath 쿼리 결과 순서.
주의 사항 :이 예제에서는 바이너리 문자열 검색 (strpos)과 DOMText :: splitText 함수로 텍스트 노드를 분할하는 데 관련된 오프셋을 사용합니다. 함수가 UTF-8 문자 오프셋을 필요로하므로 잘못된 오프셋이 발생할 수 있습니다. 올바른 방법은 mb_strpos를 사용하여 UTF-8 기반 값을 얻는 것입니다.
이 예제는 예제 데이터에 대해 UTF-8과 동일한 오프셋을 갖는 US-ASCII 만 사용하기 때문에 어쨌든 작동합니다.
실생활의 경우, $ 검색 문자열은 UTF-8로 인코딩되어야하며 mb_strpos가 strpos 대신 사용되어야합니다.
while(FALSE !== $start = mb_strpos($range, $search, 0, 'UTF-8'))
from https://stackoverflow.com/questions/8193327/ignore-html-tags-in-preg-replace by cc-by-sa and MIT license
'PHP' 카테고리의 다른 글
bbcode를 파싱하는 가장 좋은 방법 (0) | 2018.09.20 |
---|---|
PHP 오류 : 헤더 정보를 수정할 수 없습니다 - 이미 보낸 헤더 [duplicate] (0) | 2018.09.20 |
PHP 메일 : HTML을 보내는 방법? (0) | 2018.09.20 |
PHP에서 XML 파일의 속성 값을 가져 오는 방법은 무엇입니까? (0) | 2018.09.20 |
다차원 배열 값에 액세스하기 (0) | 2018.09.20 |