2013-07-02 3 views
1

HTML 코드가 포함 된 $ html이 있습니다. HTML의 어딘가에 id가 "content"인 DIV가 있습니다. 내 목표는이 DIV의 HTML 내용을 대체하는 것입니다. 이 웹 사이트에서 정규 표현식이 아닌 HTML을 사용할 때 파서를 사용하는 것이 가장 좋습니다.Perl + XPath를 사용하여 HTML로 DIV 내용 수정

지금까지 (이상적인 사용하여 XPath는) 무슨 짓을 :

my $tree= HTML::TreeBuilder::XPath->new(); 
$tree->parse_content($html); 
$content = $tree->findnodes_as_string('//div[@id="content"]'); 

이 나에게 내가 대체 할 DIV의 전체 HTML 컨텐츠를 제공합니다 ...하지만 문제는 내가 대체 할 수있는 방법입니다 이 내용? 시도했으나 작동하지 않았습니다.

$html =~ s/$content/$newhtml/mgs; 

감사합니다.

답변

2

findnodes_as_string에서 얻은 결과는 더 이상 문자열이 아니며 더 이상 문서를 보유하는 개체의 일부가 아닙니다. 객체를 출력하려면 객체 자체를 업데이트해야합니다.

findnodes을 사용하여 요소를 가져와야합니다 (일치하는 요소의 목록을 얻고 해당 목록의 첫 번째 요소를 가져옴). replace_with을 사용하여 해당 요소를 바꿀 수 있습니다. $newhtml에 마크 업이 포함 된 경우 (즉, 간단한 텍스트 콘텐츠가 아닌 경우) 객체를 replace_with에 전달해야 할 수 있습니다.

#!/usr/bin/perl 

use strict; 
use warnings; 

use HTML::TreeBuilder::XPath; 

my $html=q{<html><head><title>foo</title></head> 
       <body><div id="title">foo</div> 
         <div id="content"><p>1 para</p><p>2 para's</p></div> 
       </body> 
      </html>}; 

my $new_content='<div id="content"><p>new para 1</p><p>new para 2</p></div>'; 

my $tree= HTML::TreeBuilder::XPath->new(); 
$tree->parse_content($html); 

# findnodes erturns a list of elements, take the first one 
my $div = ($tree->findnodes('//div[@id="content"]'))[0]; 
# replace the div with an element created from $new_content 
$div->replace_with(HTML::TreeBuilder->new_from_content($new_content)); 

print $tree->as_HTML; 
+0

고맙습니다. –

0

$content은 정규식 패턴에서 특별한 의미가있는 문자 즉, *+?|[]{}^$을 포함 할 수 있습니까? 패턴을 유지하는 변수에

더 나은 탈출 메타 :

$html =~ s/\Q$content\E/$newhtml/mgs; 

(자세한 내용은 here 참조).

+0

좋은 생각하지만, 문제는 원래 $ html로 다른 HTML 엔티티가 포함되어 있기 때문에 나는, 정규식 아마 이렇게하는 가장 좋은 방법은 아니다 생각 :이 $html$newhtml#content 요소의 내용을 대체합니다 TreeBuilder가 제공하는 내용보다 ... 하나의 차이점은 정규식에서는 작동하지 않습니다. –

+0

결과에 따라 수행 할 계획에 따라 다릅니다. 제안 된 솔루션은 실제로 정규식을 적용하지 않지만 문자 그대로 대신 찾습니다. 가장 중요한 부분 인 추출은 xpath를 사용합니다. 주어진'id' 속성을 가진 요소가 선택되면, 결과 문자열은 한 번만 발생하도록 보장되어야합니다. 치환에 의해 도입 된 새로운 엔티티는, 결과가 기존의 해석 트리에 통합 할 필요가없는 경우 (예를 들어, 파일에 기입 해지는 등)에 관계 없습니다. – collapsar

3

Mojo::DOM는 HTML을 조작 할 때 나는 훨씬 간단 찾을 대신의 XPath의 CSS 선택기를 지원합니다.

use Mojo::DOM; 
my $dom = Mojo::DOM->new($html); 
$dom->at('#content')->replace_content($newhtml); 
print $dom; 
+1

또한 좋은 해결책! HTML을 사용할 때 CSS를 사용하는 것이 XPath보다 우수 할 수 있습니다. –