Nasıl PHP'nin DOMDocument html varlıkları kodlayan engellemek mi?

3 Cevap php

PHP'nin DOMDocument kullanarak bir dize Çapa 'href niteliğini değiştiren bir işlevi var. İşte bir parçacık bulunuyor:

$doc    	= new DOMDocument('1.0', 'UTF-8');
$doc->loadHTML($text);
$anchors    = $doc->getElementsByTagName('a');

foreach($anchors as $a) {
    $a->setAttribute('href', 'http://google.com');
}

return $doc->saveHTML();

Sorun loadHTML ($ metin) vb etiketleri, doctype, html, vücuttaki $ metni çevreler olduğunu. Bunun yerine loadHTML () bu yaparak bu çalışma etrafında çalıştı:

$doc    	= new DOMDocument('1.0', 'UTF-8');
$node   	= $doc->createTextNode($text);
$doc->appendChild($node);
...

Ne yazık ki, bu tüm varlıkları (ankraj dahil) kodlar. Herkes bu kapatmak için nasıl biliyor mu? Ben zaten iyice belgeler ile baktı ve onu hack çalıştı, ama onu anlamaya olamaz ettik.

Teşekkürler! :)

3 Cevap

XML has only very few predefined entities. All you html entities are defined somewhere else. When you use loadhtml() these entity definitions are load automagically, with loadxml() (or no load() at all) they are not.
createTextNode() does exactly what the name suggests. Everything you pass as value is treated as text content, not as markup. I.e. if you pass something that has a special meaning to the markup (<, >, ...) it's encoded in a way a parser can distinguish the text from the actual markup (&lt;, &gt;, ...)

$ Metin nereden geliyor? Eğer gerçek html belge içinde değiştirme yapamaz?

Ben değişen bir ince şekilde bu hack sona erdi:

return $doc->saveHTML();

içine:

$text   	= $doc->saveHTML();
return mb_substr($text, 122, -19);

Bu, değişen, tüm gereksiz Çöpü keser:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
"http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><p>
You can <a href="http://www.google.com">click here</a> to visit Google.</p>
</body></html>

Bu içine:

You can <a href="http://www.google.com">click here</a> to visit Google.

Herkes daha iyi bir şey anlamaya miyim?

Tamam, burada ben ile sona erdi nihai çözüm bulunuyor. VolkerK önerisi ile gitmeye karar verdi.

public static function ReplaceAnchors($text, array $attributeSets)
{
	$expression	= '/(<a)([\s\w\d:\/=_&\[\]\+%".?])*(>)/';

	if (empty($attributeSets) || !is_array($attributeSets)) {
		// no attributes to set. Set href="#".
		return preg_replace($expression, '$1 href="#"$3', $text);
	}

	$attributeStrs	= array();
	foreach ($attributeSets as $attributeKeyVal) {
		// loop thru attributes and set the anchor
		$attributePairs	= array();
		foreach ($attributeKeyVal as $name => $value) {
			if (!is_string($value) && !is_int($value)) {
				continue; // skip
			}

			$name				= htmlspecialchars($name);
			$value				= htmlspecialchars($value);
			$attributePairs[]	= "$name=\"$value\"";
		}
		$attributeStrs[]	= implode(' ', $attributePairs);
	}

	$i		= -1;
	$pieces	= preg_split($expression, $text);
	foreach ($pieces as &$piece) {
		if ($i === -1) {
			// skip the first token
			++$i;
			continue;
		}

		// figure out which attribute string to use
		if (isset($attributeStrs[$i])) {
			// pick the parallel attribute string
			$attributeStr	= $attributeStrs[$i];
		} else {
			// pick the last attribute string if we don't have enough
			$attributeStr	= $attributeStrs[count($attributeStrs) - 1];
		}

		// build a opening new anchor for this token.
		$piece	= '<a '.$attributeStr.'>'.preg_replace($expression, '$1 href="#"$3', $piece);
		++$i;
	}

	return implode('', $pieces);

Bu bir farklı çapa niteliklerin bir dizi işlevini çağırmak için izin verir.