2009-04-27 19 views
5

私はPhpのDOMDocumentを使って文字列のアンカーのhref属性を置き換える関数を持っています。ここでは、スニペットです:PHPのDOMDocumentがhtmlエンティティをエンコードするのを防ぐにはどうすればいいですか?

$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(); 

問題がloadHTML($テキスト)が$のDOCTYPE内のテキスト、HTML、ボディなどのタグを取り囲んでいることです。私はloadHTML()の代わりにこれを行うことでこれを回避しようとしました:残念ながら、これはすべてのエンティティ(アンカーが含まれています)をエンコードします。誰もこれをオフにする方法を知っていますか?私はすでにドキュメントを徹底的に見てハックしようとしましたが、それを理解することはできません。

ありがとうございます! :)

答えて

3
$テキストは、トリックを行う可能性がありますプレースホルダのアンカータグ

と変換された文字列です。
一般的に正規表現を使ってhtml文書を手に入れることは推奨しませんが、小さな定義済みサブセットでは適切です。

1

XMLはvery few predefined entitiesのみです。あなたのHTMLエンティティはすべて別の場所に定義されています。 loadhtml()を使用すると、これらのエンティティ定義は自動的にloadxml()(またはload()が全くない)でロードされます。
createTextNode()は、名前が示しているものとまったく同じです。価値として渡すものはすべて、マークアップではなくテキストコンテンツとして扱われます。私。あなたがマークアップ(<、>、...)に特別な意味を持つものを渡すと、パーサが実際のマークアップ(& lt; & gt; ...)とテキストを区別できるようにエンコードされます

$ textはどこから来たのですか?実際のhtml文書内で置き換えを行うことはできませんか?

+0

loadHTML、エンティティの変換は行われません。私は、mb_substr($ text、122、-19)を実行することで、問題をハッキングしてしまいました。 $ doc-> saveHTML()の結果に基づいています。 Yikes! :) $ textはプレースホルダのアンカータグで翻訳された文字列なので、置換は実行時に行う必要があります。翻訳されたリンクだけを解析するのは難しいので、私はむしろ文書全体を解析しません。 いい考えです。 – thesmart

0

私が変える、希薄な方法でこれをハッキング終わった:

return $doc->saveHTML(); 

へ:

<!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> 

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

これは、これを変更し、すべての不要なゴミを切り出し、これに:

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

誰かが良いものを見つけられますか?これらのプレースホルダは、厳格な、明確に定義された形式の簡単なpreg_replaceまたはpreg_replace_callbackをお持ちの場合は

-1

OK、ここで最後に私が解決した解決策があります。 VolkerKの提案に合意しました。

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); 

これにより、さまざまなアンカー属性のセットで関数を呼び出すことができます。

関連する問題