Я сторонник правильного английского языка (да, я знаю, что «stickler» и «correct-ish» — оксюморон). Я создал CMS для использования на сайтах моей компании, но есть одна вещь, которая действительно действует мне на нервы — создание «умных» цитат в опубликованном контенте.
У меня есть reg-ex, который делает это, но я сталкиваюсь с проблемами, когда сталкиваюсь с html-тегами в копии. Например, одна из опубликованных историй, используемых моей CMS, может содержать набор простого текста и несколько тегов HTML, например тег ссылки, который содержит кавычки, которые я НЕ хочу менять на «умные» цитаты по очевидным причинам. ,
15 лет назад я был тузом Perl RegEx, но я полностью рисую пробел на этом. То, что я хочу сделать, это обработать строку, игнорируя весь текст внутри HTML-тегов, заменить все кавычки в строке «умными» кавычками, а затем вернуть строку с ее HTML-тегами без изменений.
У меня есть функция, которую я собрал вместе для обработки наиболее распространенных сценариев, с которыми я сталкиваюсь в CMS, но я ненавижу, что это вообще некрасиво и не элегантно, и что если появляются непредвиденные теги, мое решение полностью разрушается.
Вот код (пожалуйста, не смейтесь, он набил более половины бутылки скотча):
function educate_quotes($string) {
$pattern = array('/\b"/',//right double
'/"\b/',//left double
'/"/',//left double end of line
"/(\w+)'(\w+)/",//apostrophe
"/\b'/",//left single
"/'\b/",//right single
"/'$/",//right single end of line
"/--/"//emdash
);
$replace = array("”",//right double quote
"“",//left double
"”",//left double end of line
"$1"."’"."$2",//apostrophe
"’",//left single
"‘",//right single
"’",//right single end of line
"—"//emdash
);
$string = preg_replace($pattern,$replace,$string);
//remove smart quotes around urls
$string = preg_replace("/href=“(.+)”/","href=\"$1\"",$string);
//remove smart quotes around images
$string = preg_replace("/src=“(.+?)”/","src=\"$1\" ",$string);
//remove smart quotes around alt tags
$string = str_replace('alt=”"','',$string);
$pat = "/alt=“(.+?)”/is";
$rep = "alt=\"$1\" ";
$string = preg_replace($pat,$rep,$string);
//i'm too lazy to figure out why this artifact keeps appearing
$string = str_replace("alt=“",'alt="',$string);
//same thing here
$string = preg_replace("/” target/","\" target",$string);
return $string;
}
Как я уже сказал, я знаю, что код ужасен, и я открыт для более элегантных решений. Это работает, но в будущем оно сломается, если появятся непредвиденные теги. Напомню, что я хочу повторить, что я не пытаюсь получить регулярное выражение для HTML-тегов PARSE; Я пытаюсь получить его, чтобы игнорировать их, анализируя весь остальной текст в строке.
Какие-либо решения? Я провел МНОГО онлайн-поиска и, похоже, не могу найти решение, и я незнаком с реализацией регулярных выражений в PHP, что это ужасно.
ХОРОШО. Я вроде как ответил на свой вопрос после того, как Слэкс предложил синтаксический анализ DOM, но теперь у меня проблема в том, что регулярное выражение не работает с созданными строками. Вот мой код:
function educate_quotes($string) {
$pattern = array(
'/"(\w+)"/',//quotes
"/(\w+)'(\w+)/",//apostrophe
"/'(\w+)'/",//single quotes
"/'\b/",//right single
"/--/"//emdash
);
$replace = array(
"“"."$1"."”",//quotes
"$1"."’"."$2",//apostrophe
"’"."$1"."‘",//single quotes
"‘",//right single
"—"//emdash
);
$xml = new DOMDocument();
$xml->loadHTML($string);
$text = (string)$xml->textContent;
$smart = preg_replace($pattern,$replace,$text);
$xml->textContent = $smart;
$html = $xml->saveHTML();
return $html;
}
Разбор DOM работает нормально; проблема теперь в моем регулярном выражении (которое я изменил по сравнению с предыдущим, но только до тех пор, пока приведенное выше уже не работало над созданными новыми строками) фактически не заменяет ни одну из кавычек в строках.
Кроме того, я получаю следующие раздражающие предупреждения, когда в строке есть несовершенный HTML-код:
Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: Unexpected end tag : p in Entity, line: 2 in /home/leifw/now/cms_functions.php on line 418
Поскольку я не могу рассчитывать на то, что репортеры всегда будут использовать совершенный HTML-код, это тоже проблема.
Можно ли разделить на основе HTML <
>
теги, а затем собрать его обратно вместе?
$text = "<div sdfas=\"sdfsd\" >ksdfsdf\"dfsd\" dfs </div> <span sdf='dsfs'> dfsd 'dsf ds' </span> ";
$new_text = preg_split("/(<.*?>)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
echo htmlspecialchars(print_r($new_text, 1));
так что вы получите:
Array
(
[0] =>
[1] => <div sdfas="sdfsd" >
[2] => ksdfsdf"dfsd" dfs
[3] => </div>
[4] =>
[5] => <span sdf='dsfs'>
[6] => dfsd 'dsf ds'
[7] => </span>
[8] =>
)
Тогда вы можете просто собрать все вместе, используя preg_replace, если у него нет <
>
,
Используя предложение А. Лау, я думаю, что у меня есть решение, и оказалось, что это на самом деле регулярное выражение, а не анализатор xml.
Вот мой код:
$string = '<p>"This" <b>is</b> a "string" with <a href="http://somewhere.com">quotes</a> in it. <img src="blah.jpg" alt="This is an alt tag"></p><p>Whatever, you know?</p>';
$new_string = preg_split("/(<.*?>)/",$string, -1, PREG_SPLIT_DELIM_CAPTURE);
echo "<pre>";
print_r($new_string);
echo "</pre>";
for($i=0;$i<count($new_string);$i++) {
$str = $new_string[$i];
if ($str) {
if (strpos($str,"<") === false) {
$new_string[$i] = convert_quotes($str);
}
}
}
$str = join('',$new_string);
echo $str;
function convert_quotes($string) {
$pattern = array('/\b"/',//right double
'/"\b/',//left double
'/"/',//left double end of line
"/(\w+)'(\w+)/",//apostrophe
"/\b'/",//left single
"/'\b/",//right single
"/'$/",//right single end of line
"/--/"//emdash
);
$replace = array("”",//right double quote
"“",//left double
"”",//left double end of line
"$1"."’"."$2",//apostrophe
"’",//left single
"‘",//right single
"’",//right single end of line
"—"//emdash
);
return preg_replace($pattern,$replace,$string);
}
Этот код выводит следующее:
Array (
> [0] =>
> [1] => <p>
> [2] => "This"> [3] => <b>
> [4] => is
> [5] => </b>
> [6] => a "string" with
> [7] => <a href="http://somewhere.com">
> [8] => quotes
> [9] => </a>
> [10] => in it.
> [11] => <img src="blah.jpg" alt="This is an alt tag">
> [12] =>
> [13] => </p>
> [14] =>
> [15] => <p>
> [16] => Whatever, you know?
> [17] => </p>
> [18] => >
> Whatever, you know?
«Это» — «строка» с кавычками. Это альтернативный тег
Знаете что?