it-swarm.com.de

So ersetzen Sie den Inhalt von Div für das Plugin

Ich schreibe ein Plugin für das Virtuemart System Plugin. In ihrer älteren Version (VM2.x) haben sie das Div einfach mit einer Klasse verwaltet und es gibt keine innere Div Struktur, so dass preg_replace Für meine Anforderung ausreicht. Aber in der neuen Version wurde die Div-Standardstruktur geändert. Div inside Div is there. Daher kann preg_replace Nicht den gesamten Div Inhalt ersetzen.

Früher habe ich es nur mit PHPDom und Xpath verwaltet, aber in einigen Template-Frameworks (T3) Hat meine Plugin-Aktivierung einen Fehler zurückgegeben.

"0 - String could not be parsed as XML"

das gleiche Plugin funktioniert auch mit Gantry und anderen Frameworks. In der alten Version habe ich den folgenden Code ausprobiert und er funktioniert auf allen Vorlagen einwandfrei.

$buffer = preg_replace('<div class="ClassNeedstoReplace">([^`]*?)<\/div>/','my custom content',$buffer);    

Jetzt in Vm3 verwende ich folgende Codes.

$docs = new DOMDocument();
libxml_use_internal_errors(true);
$docs->resolveExternals = true;
$docs->loadHTML($buffer);
if($getRelatedProduct != '')
$element = $docs->createElement('div', $getRelatedProduct);
$xpath = new DOMXPath($docs);
$query = '//div[@class="'.$class_name.'"]';
$entries = $xpath->query($query);
foreach ($entries as $entry) {

    $entry->parentNode->replaceChild($element, $entry);
}
$docs->recover = true;
libxml_clear_errors();
JResponse::setBody(htmlspecialchars_decode($docs->saveHTML()));

bcoz alle Instanz der Klasse muss ersetzt werden.

Ich weiß, dass zum Testen des Plugins eine andere Erweiterung (VM3) erforderlich ist, die für Debugger schwierig ist. Aber einfach meine Anforderung ist, einfach die gesamte Klasseninstanz durch meine zu ersetzen.

gibt es eine Möglichkeit, Div innerhalb der Div-Struktur zu ersetzen, ohne Layouts mit preg_replace zu unterbrechen?

Die Div Struktur ist

<div class="product-fields">
        <div class="product-field product-field-type-R">
                                    <span class="product-fields-title-wrapper"><span class="product-fields-title"><strong>Related Products</strong></span>
                        <span title="" class="hasTooltip" data-original-title="&lt;strong&gt;Related Products&lt;/strong&gt;&lt;br /&gt;COM_VIRTUEMART_RELATED_PRODUCTS_TIP"><img alt="Tooltip" src="/j34/media/system/images/tooltip.png"></span></span>
                <span class="product-field-display"><a target="blank" title="Test Product 1" href="/j34/index.php/shops/c1/t1-detail">Test Product 1</a></span><span class="product-field-desc">Custom prototype for related products</span>            </div>
        </div>

Ich versuche, "product-field product-field-type-R" Zu ersetzen, es kann mehr als eine innerhalb "product-fields" Kommen

Hoffe, jemand wird in der Lage sein, etwas herauszufinden :)

3
Jobin Jose

Mögliche andere Lösungen:

Es gibt einige graue Details in Ihrer Frage, also werde ich eine Lösung posten, was ich denke wird nach Belieben mit DOMDocument und einer direkten XPath-Abfrage ausgeführt. Da Ihre Frage anscheinend nur ein generiertes Element enthält und Sie ein oder mehrere unerwünschte Elemente entfernen müssen, entfernt meine Lösung jedes unerwünschte Element mit Ausnahme des ersten und ersetzt dann das erste unerwünschte Element durch das erstellte Element.

Die Schleife wiederholt alle <div> Tags, die Klassenwerte enthalten: product-field und product-field-type-R UND habe einen direkten Elternteil <div> mit einem Klassenwert von product-fields. contains bietet eine erhöhte Flexibilität, da es nicht unterbrochen wird, wenn neue Klassenwerte hinzugefügt werden.

Code: ( Demo )

$html = /* your valid incoming html */;
$getRelatedProduct = "Flashy, shiny, new";

libxml_use_internal_errors(true);
$dom = new DOMDocument; 
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$element = $dom->createElement('div', $getRelatedProduct);

$xpath = new DOMXPath($dom);
$nodes = $xpath->query("//div[contains(@class, 'product-fields')]/div[contains(@class, 'product-field') and contains(@class, 'product-field-type-R')]");
for ($i = $nodes->length - 1; $i >= 0; --$i) {  // when removing nodes from DOM, work in reverse order for stability
    $node = $nodes->item($i);
    if ($i) { 
        //$trailing_whitespace = $node->nextSibling;
        $node->parentNode->removeChild($node);    // remove any qualifying element that IS NOT the first element
        //$trailing_whitespace->parentNode->removeChild($trailing_whitespace);  // optionally remove line returns after removed tags
    } else {
        $node->parentNode->replaceChild($element, $node);  // replace the first element with the generated element
    }
}

echo $dom->saveHTML();

Die Verwendung von DomDocument & XPath macht diese Lösung robuster als reguläre Ausdrücke, da die gewünschten Elemente auch dann noch übereinstimmen, wenn Dritte die Klassenattributwerte umstrukturieren.

2
mickmackusa