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

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

Мне нужно регулярное выражение для соответствия только & , > и < chars, которые существуют внутри строки части любого узла 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; 

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

Правильный XML

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

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

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

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

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

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

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

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

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

вы и я, вероятно, можем догадаться, что результат должен быть: ...containing &lt; and &gt;... ...containing &lt; and &gt;... но я уверен, что спецификация XML допускает дополнительные пробелы, поэтому официально «<и>» следует рассматривать как тег. Вы могли бы, я полагаю, предположить, что все, что похоже на не совпадающий тег, действительно не предназначено для тега, но это тоже займет определенную работу.

В конце концов я решил использовать библиотеку 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.

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

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

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

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

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

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

 /(\s+)(>)(\s+)/gim "$1&gt;$2" /(\s+)(<)(\s+)/gim "$1&lt;$2" 

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

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

Предполагается ли, что <br/> читать &lt;br/&gt; ? Невозможно узнать, потому что это правильно отформатированный XML.

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

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

Если источник содержит строки типа «<something», где «что-то» соответствует произведению для имени:

Имя :: = NameStartChar (NameChar) *

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

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