Регулярное выражение для совпадения символов «>», «<», «&», которые появляются внутри узлов XML

Я пытаюсь написать регулярное выражение, используя библиотеку PCRE в PHP.

Мне нужно регулярное выражение, чтобы соответствовать только символам &, > и <, которые существуют внутри строковой части любого узла XML, а не самим объявлениям тегов.

Входной XML:

<pnode>
  <cnode>This string contains > and < and & chars.</cnode>
</pnode>

Идея состоит в том, чтобы искать и заменять эти символы и преобразовывать их в эквиваленты сущностей XML.

Если бы я должен был преобразовать весь XML в сущности, XML бы выглядел так:

Весь XML преобразуется в сущности

&lt;pnode&gt;
  &lt;cnode&gt;This string contains &gt; and &lt; and &amp; chars.&lt;/cnode&gt;
&lt;/pnode&gt;

I нужно, чтобы это выглядело так:

Правильный XML

<pnode>
  <cnode>This string contains &gt; and &lt and &amp; chars.</cnode>
</pnode>

Я попытался написать регулярное выражение для сопоставления этих символов, используя look-ahaead, но я не не знаю достаточно, чтобы заставить это работать. Моя попытка (в настоящее время только пытается сопоставить> символы):

/>(?=[^<]*<)/g

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

10
задан Alan Moore 18 February 2010 в 00:15
поделиться

7 ответов

В итоге я решил использовать библиотеку Tidy в PHP. Код, который я использовал, показан ниже:

  // Specify configuration
  $config = array(
    'input-xml'  => true,
    'show-warnings' => false,
    'numeric-entities' => true,
    'output-xml' => true);

  $tidy = new tidy();
  $tidy->parseFile('feed.xml', $config, 'latin1');
  $tidy->cleanRepair()

Он отлично работает, исправляя все ошибки кодирования и преобразовывая недопустимые символы в объекты XML.

2
ответ дан 4 December 2019 в 03:16
поделиться

Я вполне уверен, что это просто невозможно. Вам нужно что-то, что отслеживает вложенность, и нет никакого способа получить регулярное выражение для отслеживания вложенности. Ваш выбор - сначала исправить текст (когда вы, вероятно, можете использовать RE) или использовать что-то, хотя бы отдаленно напоминающее синтаксический анализатор XML, в частности, для отслеживания того, как теги вложены.

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

    <tag>Text containing < and > characters</tag>

мы с вами, вероятно, можем предположить, что результат должен быть: ... содержащий <и> ... , но я почти уверен, что спецификация XML разрешает лишний пробел, поэтому официально "<и>" следует рассматривать как тег. Я полагаю, вы могли бы предположить, что все, что выглядит как несоответствующий тег, на самом деле не предназначено для использования в качестве тега, но это тоже потребует некоторой работы.

2
ответ дан 4 December 2019 в 03:16
поделиться

Можно ли перехватить текст, прежде чем он попытается стать частью вашего XML? Несколько унций профилактики могут стоить фунтов лечения.

0
ответ дан 4 December 2019 в 03:16
поделиться

Это должно сделать это для амперсандов:

/(\s+)(&)(\s+)/gim

Это означает, что вы ищете эти символы только тогда, когда они имеют пробелы с обеих сторон.

Просто убедитесь, что заменяющим выражением является "$ 1 $ 2amp; $ 3";

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

/(\s+)(>)(\s+)/gim   "$1&gt;$2"
/(\s+)(<)(\s+)/gim   "$1&lt;$2"
0
ответ дан 4 December 2019 в 03:16
поделиться

То, что у вас есть, конечно, не XML. В XML символы «<» и «&» не могут встречаться (без экранирования) внутри текста: только внутри комментария, раздела CDATA или инструкции обработки. Фактически, '>' может встречаться в тексте, за исключением части строки ']]>'. В правильно сформированном XML буквальные символы '<' и '&' сигнализируют о начале разметки: '<' сигнализирует о начале начального тега, конечного тега или тега пустого элемента, а '&' сигнализирует о начале объекта. Справка. В обоих этих случаях следующий символ НЕ может быть пробелом. Таким образом, использование RE, такого как предложение Робусто, обнаружит все такие случаи. Вам также может потребоваться отловить угловые случаи, такие как '<<', '<\' или '& <'. В этом случае вам не нужно пытаться анализировать введенные вами данные, RE будет работать нормально.

Если источник содержит такие строки, как «

Name :: = NameStartChar (NameChar) *

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

Лучше всего использовать RE, чтобы отловить 90% ошибок и исправить остальные вручную. Вам нужно искать '<' или '&', за которым следует что-либо, кроме NameStartChar

0
ответ дан 4 December 2019 в 03:16
поделиться

Как утверждали другие, регулярные выражения плохо справляются с иерархическими данными. Кроме того, если данные неправильно отформатированы, вы не можете гарантировать, что у вас все получится. Подумайте:

<xml>
    <tag>Something<br/>Something Else</tag>
</xml>

Это
должно читать
? Нет никакого способа узнать, потому что это правильно отформатированный XML.

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

0
ответ дан 4 December 2019 в 03:16
поделиться

Классический пример мусора на входе и выходе. Реальное решение - исправить сломанный экспортер XML, но, очевидно, это выходит за рамки вашей проблемы. Похоже, вам, возможно, придется вручную проанализировать XML, запустить htmlentites () для содержимого, а затем вернуть теги XML.

2
ответ дан 4 December 2019 в 03:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: