2011-01-13 5 views
7

Ich versuche, bestimmte Links abhängig von ihrem ID-Tag zu entfernen, aber den Inhalt des Links verlassen. Zum Beispiel möchte ichPHP Dom Element entfernen Inhalt verlassen

Some text goes <a href="http://www.domain.tdl/" id="remove">here</a> 

zu

Some text goes here 

ich die unter Verwendung haben versucht, drehen.

$dom = new DOMDocument; 
$dom->loadHtml(mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8")); 
$xp = new DOMXPath($dom); 

foreach($xp->query('//a[contains(@id="remove")]') as $oldNode) { 
$revised = strip_tags($oldNode); 
} 

$revised = mb_substr($dom->saveXML($xp->query('//body')->item(0)), 6, -7, "UTF-8"); 
echo $revised; 

grob aus here genommen, aber es spuckt nur den gleichen Inhalt von $html zurück.

Irgendwelche Ideen, wie ich das erreichen würde?

+0

Sie ändern Ihr Dokument hier nicht, deshalb spuckt es den gleichen Inhalt. Beispiel: Sie haben 'replaceChild' auf dem DOM-Objekt aufgerufen, und Sie erstellen gerade eine Variable, die Sie später mit einer Ausgabe von' saveXML' überschreiben. –

+0

Gute Frage, +1. Siehe meine Antwort auf eine einzelne XPath-Ausdruckslösung, die genau die gewünschten Knoten auswählt. :) –

Antwort

12

, die für diese meine Funktion ist:

function DOMRemove(DOMNode $from) { 
    $sibling = $from->firstChild; 
    do { 
     $next = $sibling->nextSibling; 
     $from->parentNode->insertBefore($sibling, $from); 
    } while ($sibling = $next); 
    $from->parentNode->removeChild($from);  
} 

So folgt aus:

$dom->loadHTML('Hello <a href="foo"><span>World</span></a>'); 
$a = $dom->getElementsByTagName('a')->item(0); // get first 
DOMRemove($a); 

Sollten Sie geben:

Hello <span>World</span> 

Knoten mit einer bestimmten ID zu erhalten, XPath verwenden:

$xpath = new DOMXpath($dom); 
$node = $xpath->query('//a[@id="something"]')->item(0); // get first 
DOMRemove($node); 
+0

Ich habe mir diesen Code in einem anderen Post angesehen, aber a) Ich bekomme einen Fehler 'Schwerwiegender Fehler: Aufruf an eine Memberfunktion insertBefore() auf einem Nicht-Objekt' und b) Wie würde ich das anpassen? Entferne nur die a-Elemente mit einer bestimmten ID? – Jack

+0

@Jack: Tut mir leid, mein Fehler, das Funktionsargument sollte '$ from' sein und nicht' $ node'. Fest. Danke, dass du darauf hingewiesen hast. Außerdem wurde ein Beispiel zum Abrufen eines Knotens mit einer bestimmten ID hinzugefügt. – netcoder

+0

Zwei Fragen; Wie würde ich die überarbeiteten Daten ausgeben? Und wenn ich das Beispiel verwende, das Sie für bestimmte IDs angegeben haben, bekomme ich denselben Fehler wie zuvor. – Jack

1

Verwenden:

//a[@id='remove']/node() 
| 
//*[a[@id='remove']]/node()[not(self::a[@id=''remove])] 

Dies wählt alle Kinder jeden a Attribut id mit Wert "remove" und alle vorhergehenden und nachfolgenden Geschwister dieser a, die nicht selbst eine andere a mit Attribut id mit dem Wert von "remove"

2

Ein Ansatz ähnlich der Antwort von @ netcoder, aber mit einer anderen Schleifenstruktur und DOMElement-Methoden.

$html = '<html><body>This <a href="http://www.domain.tdl/" id="remove">link</a> was removed.</body></html>'; 
$dom = new DOMDocument(); 
$dom->loadHTML($html); 
$xpath = new DOMXPath($dom); 
foreach ($xpath->query('//a[@id="remove"]') as $link) { 
    // Move all link tag content to its parent node just before it. 
    while($link->hasChildNodes()) { 
    $child = $link->removeChild($link->firstChild); 
    $link->parentNode->insertBefore($child, $link); 
    } 
    // Remove the link tag. 
    $link->parentNode->removeChild($link); 
} 
$html = $dom->saveXML(); 
+0

Kann '$ child = $ link-> removeChild ($ link-> firstChild);' einfach als '$ child = $ link-> firstChild geschrieben werden;'? – myol

Verwandte Themen