Замена кодировки на preg_replace

у меня есть содержимое различных веб-сайтов, хранящееся в переменной с именем $content. Теперь то, что я хотел бы сделать, это выполнить поиск содержимого для META-тегов следующим образом:

<meta http-equiv="Content-type" content="text/html; charset=utf-8" />

А затем замените utf-8 на IS0-8859-1. Как мне это сделать с preg_replace?

Обратите внимание, что каждый случай не похож на этот метатег. Это может отличаться в зависимости от того, какой веб-сайт вы выбираете.


person Community    schedule 16.08.2009    source источник
comment
Извините, но я все еще не понимаю, о чем вы спрашиваете. Если вы просто хотите заменить UTF-8 на ISO-8859-1, то мой ответ подойдет.   -  person Josh Leitzel    schedule 16.08.2009
comment
Да, я проверил это, и он отлично работает. Но почему некоторые персонажи веб-сайтов все еще странные? Вроде ÅÄÖ очень странно. Он превратился в ä   -  person    schedule 16.08.2009


Ответы (3)


Вам не нужно использовать preg_replace для этого. Просто используйте str_replace:

$content = str_replace('; charset=utf-8', '; charset=ISO-8859-1', $content);
person Josh Leitzel    schedule 16.08.2009
comment
Прочитайте, что я прокомментировал пост karim79. :) - person ; 16.08.2009
comment
Это выглядит как самое простое решение... Но что произойдет, если ; charset=utf-8 в другом месте страницы? Например, что произойдет, если этот участок кода будет использоваться на этой странице, содержащей ; charset=utf-8 string несколько раз в своем содержании (в этом самом ответе, например ^^ ) ? - person Pascal MARTIN; 16.08.2009
comment
@Pascal MARTIN - тогда можно использовать более полную строку - см. мой ответ;) - person karim79; 16.08.2009

Как насчет такого:

$input = 'sometext<meta http-equiv="Content-type" content="text/html; charset=utf-8" />someothertext';

$output = preg_replace('#<meta http-equiv="Content-type" content="text/html; charset=(utf-8)" />#', 
    '<meta http-equiv="Content-type" content="text/html; charset=IS0-8859-1" />', 
    $input);

var_dump($output);

Который просто заменяет первую строку второй, давая вам:

string 'sometext<meta http-equiv="Content-type" content="text/html; charset=IS0-8859-1" />someothertext' (length=95)

Конечно, это учитывая, что входная мета всегда одна и та же, всегда пишется одинаково, с атрибутами в одном и том же порядке и все такое.

Регулярное выражение может быть более щадящим:

$output = preg_replace('#<meta\s+http-equiv="Content-type"\s+content="text/html;\s+charset=(utf-8)"\s+/>#', 
    '<meta http-equiv="Content-type" content="text/html; charset=IS0-8859-1" />', 
    $input);

Конечно, это все еще не на самом деле снисходительно ^^


Но, если вы знаете, что метаданные, используемые в качестве входных данных, всегда будут одинаковыми, вам не нужно регулярное выражение ; Полагаю, str_replace отлично справится с этой задачей...

Что-то вроде этого :

$output = str_replace('<meta http-equiv="Content-type" content="text/html; charset=utf-8" />', 
    '<meta http-equiv="Content-type" content="text/html; charset=IS0-8859-1" />', 
    $input);
var_dump($output);

Что дает вам тот же результат:

string 'sometext<meta http-equiv="Content-type" content="text/html; charset=IS0-8859-1" />someothertext' (length=95)



ИЗМЕНИТЬ после комментариев и редакции OP
(Да, я видел, что другой ответ, основанный на str_replace, был принят... тем не менее, возможно, это будет полезно)< /эм>

Если вы действительно хотите манипулировать HTML, который не является «фиксированным», над которым у вас нет контроля, может быть лучше вообще не использовать регулярное выражение, но какой-то инструмент создан именно для этого.

Например, объединенный класс DOMDocument и DOMDocument::loadHTML может помочь; возможно, в сочетании с некоторыми запросами XPath - даже если это похоже на тяжелую артиллерию ^^

Для получения дополнительной информации вы можете взглянуть на этот ответ, который я дал на другой вопрос несколько дней назад...

И в вашем случае, вероятно, будет что-то вроде этого:

$input = <<<HTML
<html>
<head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>Test</title>
</head>
<body>
    <p>Hello, world!</p>
</body>
</html>
HTML;

$dom = new DOMDocument();
$dom->loadHTML($input);

$xpath = new DOMXpath($dom);
$metas = $xpath->query('//meta[@http-equiv="Content-type"]');

if ($metas->length > 0) {
    $meta = $metas->item(0);
    $attribute = $meta->getAttribute('content');
    if (strpos($attribute, 'text/html') === 0) {
        $meta->setAttribute('content', 'text/html; charset=ISO-8859-1');
    }
}

echo $dom->saveHTML();

Наиболее интересные части:

  • Вы используете парсер DOM со стандартными методами DOM
  • Вы можете выполнять запросы XPath, чтобы найти именно тот элемент, который вам нужен.


Результирующий HTML будет выглядеть следующим образом:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1">
<title>Test</title>
</head>
<body>
    <p>Hello, world!</p>
</body>
</html>

Может быть, немного тяжелее и требует больше кода ... Но с этим он всегда должен работать (ну, я полагаю, до тех пор, пока HTML, используемый в качестве ввода, не слишком испорчен).

И это будет работать для всего остального в документе ;-)


Возможно, в вашем случае это чересчур, но, если повезет, вы вспомните об этом в тот день, когда вам нужно будет разобрать HTML, и вам не придется бороться с/против какого-либо мутантного регулярного выражения ^^


Да, и, конечно же: изменение мета-типа контента не изменит реальную кодировку вашего контента: вам все равно придется делать это самостоятельно, если это необходимо (например, см. icv или utf8_decode)

Вам также может потребоваться изменить заголовок HTTP Content-type (не знаю, как браузеры обрабатывают метаданные, если/когда установлен заголовок HTTP)

person Pascal MARTIN    schedule 16.08.2009
comment
Спасибо за ваше время, но вы должны прочитать, что я прокомментировал другие сообщения. Потому что каждый случай не такой ... - person ; 16.08.2009
comment
OK о чтении комментариев к другим сообщениям ; в этот момент есть только один другой ответ, и единственный комментарий, который у него есть, это «Прочитайте то, что я прокомментировал сообщение karim79». :) ^^ Итак... ок :-D Полагаю, karim79 удалил свой ответ ^^ ; если ваш вопрос отличается от того, что вы задали в ОП, мы не можем догадаться, что это такое ;-) вам следует отредактировать ОП, чтобы задать полный вопрос; так будет проще вам помочь :-) - person Pascal MARTIN; 16.08.2009
comment
Я отредактировал свой ответ, чтобы дать немного больше информации; это может быть немного тяжело, но может быть полезно в один прекрасный день или другой ^^ - person Pascal MARTIN; 16.08.2009

вы можете просто сопоставить «charset = *» и заменить *, что бы это ни было, на «ISO-8859-1».

Что-то вроде этого:

$content = preg_replace('/(charset=)(.+)\"/', "$1"."ISO-8859-1", $content);
person Johan    schedule 01.07.2010