PHP: Escape-кавычки ТОЛЬКО вне HTML-тегов (Regex) - PullRequest
1 голос
/ 17 апреля 2009

Какое регулярное выражение может идентифицировать двойные кавычки за пределами HTML-тегов (которые уже будут проверены), чтобы экранировать их до "?

Ответы [ 6 ]

6 голосов
/ 17 апреля 2009

Нет такого регулярного выражения.

<p>
  <!-- <a href=" --> is this outside " a tag <!-- "> foo </a> --> or not?
</p>

Если вы хотите сделать это, вам, к сожалению, придется использовать анализатор HTML. Поскольку вы уже проверили HTML, у вас, вероятно, уже есть анализатор для использования.

1 голос
/ 17 апреля 2009

Не используйте для этого регулярное выражение, используйте (или напишите) парсер.

В следующем коде предполагается, что входная HTML-строка правильно сформирована (как вы сказали). Имейте в виду, что код сломается, если он обнаружит неверный ввод!

Если вы не уверены в правильности формы, вы можете попробовать PHP Tidy .

<?php
$html = '<tag>text "text"<tag attr="value"><!-- "text" --> text</tag> "text".';
echo html_escape_quotes($html);

/* Parses input HTML and escapes any literal double quotes 
   in the text content with &quot;. Leaves comments alone.  */
function html_escape_quotes($html)
{
  $output = "";
  $length = strlen($html);
  $delim  = "<";
  $offset = 0;
  while ($offset < $length) {
    $tokpos = strpos($html, $delim, $offset);
    if ($tokpos === false) $tokpos = $length;

    $token  = substr($html, $offset, $tokpos - $offset);
    $offset = $tokpos;

    if ($delim == "<") {
      $token = str_replace('"', '&quot;', $token);
      $delim = substr($html, $offset, 4) == "<!--" ? "-->" : ">";
    } else {
      $delim = "<";
    }

    $output .= $token;
  }
  return $output;
}
?>
0 голосов
/ 18 сентября 2009

Не самый лучший (работает не во всех ситуациях), но достаточно для меня:

function quoting(&$data) {
    $quot  = '(["\x93\x94\x84]|\&#8220;|\&#8222;|\&#8221;|\&ldquo;|\&bdquo;|\&rdquo;|\&quo;|\&#34;)';
    $parse = '<q>$2</q>';
    $data  = preg_replace('/="([^"]*)"/', '*%Q:$1%*', $data);
    $data  = preg_replace("/$quot(.*?)$quot/", $parse, $data);
    $data  = preg_replace('/\*%Q:(.*?)%\*/', '="$1"', $data);
}
0 голосов
/ 17 апреля 2009

Вы можете попытаться разбить строку и отделить теги от текстовых данных с помощью этого выражения:

<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>

Это будет (надеюсь) соответствовать любому XML PI, тегу элемента, CDATA и блоку комментариев.

Итак:

$parts = preg_split('/(<(?:\?[^?]+\?>|[A-Za-z]+(?:[^">]+|"[^"]*")*|!(?:\[CDATA\[(?:[^\]]+|](?:[^\]]|][^>]))*]]|--(?:[^-]+|-(?!->))*--))>)/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$str = '';
foreach ($parts as $part) {
    if ($part[0] == '<') {
        $str .= $part;
    } else {
        $str .= str_replace('"', '&quot;', $part);
    }
}

Но я сомневаюсь, что это очень эффективно. Настоящий парсер был бы более эффективным и правильным.

0 голосов
/ 17 апреля 2009

Это возможно.

Вы можете сделать это с помощью регулярного выражения, с чем-то похожим на приведенное ниже. Вам придется запускать его несколько раз, поскольку это регулярное выражение заменяет только 1 "на" между тегами.

Serach: (\<.+?\>.+?)(")(.+?\</.+?\>)
Replace: $1'$3

Но лучшим подходом было бы использование обратных вызовов для замены функций. Просто создайте RE, который отправляет содержимое тегов в функцию, которая затем может просто заменить "на что угодно.

Подробнее здесь . Поиск обратного звонка. Как заметил Дероберт, вам может потребоваться удалить комментарии до этого:)

0 голосов
/ 17 апреля 2009

это будет работать?

\"(?!\s*\w*>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...