Regex: удалить разрывы строк из частей строки (PHP) - PullRequest
3 голосов
/ 27 июля 2010

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

Пример XML-источника:

<resources>
  <resource>
    <id>001</id>
    <name>Resource name 1</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor. Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.</desc>
  </resource>
  <resource>
    <id>002</id>
    <name>Resource name 2</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor. Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.
</desc>
  </resource>
  <resource>
    <id>003</id>
    <name>Resource name 3</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor.
Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.
</desc>
  </resource>
</resources>

Мое понимание:

$pattern = "#(\t\t<[^>]*>[^<>]*)[\r\n]+([^<>]*</.*>)#";
$replacement = "$1$2";
$data = preg_replace($pattern, $replacement, $data);

Этот шаблон исправляет 2-й ресурс и возвращает его на свою строку.Тем не менее, он не исправляет 2 разрывов строк из 3-го ресурса, а только один.В результате получается:

<resources>
  <resource>
    <id>001</id>
    <name>Resource name 1</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor. Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.</desc>
  </resource>
  <resource>
    <id>002</id>
    <name>Resource name 2</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor. Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.</desc>
  </resource>
  <resource>
    <id>003</id>
    <name>Resource name 3</name>
    <desc>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nibh magna, fermentum et pretium vel, malesuada sit amet dolor.
Morbi dictum, nunc sed interdum facilisis, ligula enim pharetra tortor, at egestas urna massa non nulla.</desc>
  </resource>
</resources>

Что не так с моим шаблоном?

Ответы [ 3 ]

3 голосов
/ 28 июля 2010

Первый [^<>]* в вашем регулярном выражении сначала сожирает весь оставшийся текст, а затем должен откатить пути, чтобы остальные регулярные выражения могли совпадать. Он только возвращается на обратный путь, то есть к разрыву строки last в тексте. Остальная часть регулярного выражения может соответствовать тому, что осталось, вот и все.

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

preg_replace('#[\r\n]+(?=[^<>]*</desc>)#', ' ', $data);

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

Вы не можете иметь предпросмотр совпадения только с любым конечным тегом (</\w+>), потому что это позволит ему соответствовать разрывам строк между элементами, а также внутри них. Однако вы можете перечислить элементы, с которыми хотите работать:

</(?:desc|name|id)>
2 голосов
/ 27 июля 2010

Если вы пытаетесь сделать гораздо больше, чем вы описываете, я думаю, вы слишком усложняете. Вам не нужно почти такое же сложное регулярное выражение, как у вас. Попробуйте просто использовать /\r?\n. Это сработало для меня с вашими данными:

$data = preg_replace("/\r?\n/", "", $data);
1 голос
/ 27 июля 2010

Что не так с моим шаблоном?

Это шаблон, а не анализатор XML.

Попробуйте использовать DOM или один из много, много настоящих парсеров XML, доступных для PHP .Это должен быть простой вопрос прохождения всех текстовых узлов и trim их объединения.

...