2011-08-28 19 views
5

I utiliza doc dom para cargar código HTML de base de datos de la siguiente manera:Documentos PHP Dom: conseguir textContent haciendo caso omiso de las etiquetas y comentarios del guión

$doc = new DOMDocument(); 
@$doc->loadHTML($data); 
$doc->encoding = 'utf-8'; 
$doc->saveHTML(); 

entonces consigo el cuerpo del texto haciendo siguientes:

$bodyNodes = $doc->getElementsByTagName("body"); 
$words = htmlspecialchars($bodyNodes->item(0)->textContent); 

Las palabras que he recibido incluyen todo en el <body>. Cosas como <scripts> también fueron incluidas. ¿Cómo los elimino y solo guardo el contenido de texto real?

+0

que significa el contenido del texto extracto de recursiva de todos los elementos de '' ? –

+0

solo texto contenido que sea significativo, excluyendo javascripts u otros comentarios html o etc. que no son datos útiles. – nuttynibbles

Respuesta

5

Tienes que visitar todos los nodos y regresar su texto. Si algunos contienen otro nodo, visítalos también.

Esto se puede hacer con este algoritmo recursivo básica:

extractNode: 
    if node is a text node or a cdata node, return its text 
    if is an element node or a document node or a document fragment node: 
     if it’s a script node, return an empty string 
     return a concatenation of the result of calling extractNode on all the child nodes 
    for everything else return nothing 

Implementación:

function extractText($node) {  
    if (XML_TEXT_NODE === $node->nodeType || XML_CDATA_SECTION_NODE === $node->nodeType) { 
     return $node->nodeValue; 
    } else if (XML_ELEMENT_NODE === $node->nodeType || XML_DOCUMENT_NODE === $node->nodeType || XML_DOCUMENT_FRAG_NODE === $node->nodeType) { 
     if ('script' === $node->nodeName) return ''; 

     $text = ''; 
     foreach($node->childNodes as $childNode) { 
      $text .= extractText($childNode); 
     } 
     return $text; 
    } 
} 

Esto devolverá el textContent del nodo $ dado, haciendo caso omiso de las etiquetas y comentarios del guión.

$words = htmlspecialchars(extractText($bodyNodes->item(0))); 

Inténtelo aquí: http://codepad.org/CS3nMp7U

+0

esto funciona. si no te importa, ¿podrías explicar el código? – nuttynibbles

+0

He agregado una descripción rápida del algoritmo – arnaud576875

5

Usted puede utilizar XPath para esto.

Tomando prestado el HTML Arnaud utilizado por su ejemplo anterior:

$html = <<< HTML 
<p> 
    test<span>foo<b>bar</b> 
</p> 
<script> 
    ignored 
</script> 
<!-- comment is ignored --> 
<p>test</p> 
HTML; 

Simplemente query todo text nodes que no son not children of a script tag y do not evaluate to an empty string. También se asegurará de no preserveWhiteSpace, por lo que no se considera el espacio en blanco utilizado para el formateo.

$dom = new DOMDocument; 
$dom->preserveWhiteSpace = false; 
$dom->loadHtml($html); 

$xp = new DOMXPath($dom); 
$nodes = $xp->query('/html/body//text()[ 
    not(ancestor::script) and 
    not(normalize-space(.) = "") 
]'); 

foreach($nodes as $node) { 
    var_dump($node->textContent); 
} 

es la salida (demo)

string(10) " 
    test" 
string(3) "foo" 
string(3) "bar" 
string(4) "test" 
+0

Esta función ayuda. en realidad es capaz de reconocer y dividir oraciones de palabras como una cadena. – nuttynibbles

+0

@nuttynibbles no reconoce palabras, ni oraciones. XPath es un lenguaje de consulta para XML. No tiene ninguna pista sobre el contenido de un documento XML, solo sobre la estructura. Ver [mi respuesta aquí para una introducción a los conceptos DOM] (http://stackoverflow.com/questions/4979836/noob-question-about-domdocument-in-php/4983721#4983721) – Gordon

Cuestiones relacionadas