2011-10-06 4 views
2

У меня есть файл «XML-файл», который имеет некоторые нежелательные символы в немPython нежадное регулярное выражения, чтобы очистить XML

<data> 
    <tag>blar </tag><tagTwo> bo </tagTwo> 
    some extra 
    characters not enclosed that I want to remove 
    <anothertag>bbb</anothertag> 
</data> 

Я думал следующее нежадной подмена удалят символы, которые не были должным образом облицованными в <sometag></sometag>

re.sub("</([a-zA-Z]+)>.*?<","</\\1><",text) 
      ^  ^^ ^ text is the xml txt. 
     remember tag, | |  put tag back without and reopen next tag 
       read everything until the next '<' (non-gready) 

Это регулярное выражение, кажется, только чтобы найти положение, обозначенное с [[]] в </tag>[[]]<tagTwo> Что я делаю неправильно?

EDIT: мотивация на этот вопрос был решен (см комментарии, у меня была шальная & в файле XML, который вызывает не разобрать - это не имеет ничего общего с персонажами, которые я хочу Удалить). Тем не менее, мне все еще интересно узнать, возможно ли регулярное выражение (и что было не так с моей попыткой), и поэтому я не исключаю вопрос.

+0

@cwallenpoole: Я не пытаюсь разобрать XML. Я пытаюсь очистить XML-файл, чтобы я мог его принять парсером. Любые предложения, не связанные с регулярным выражением, о том, как это сделать, приветствуются – Tom

+0

Какой парсер этого не принимает? –

+0

@ IgnacioVazquez-Abrams 'xml.dom.mindom' Я редактировал вопрос, чтобы включить backtrace – Tom

ответ

3

Точка не соответствует символам новой строки, если вы не указали флаг re.DOTALL.

re.sub("</([a-zA-Z]+)>.*?<","</\\1><",text, flags=re.DOTALL) 

должен работать нормально. (Если это не так, мой питон виноват, а не регулярное выражение. Пожалуйста, исправьте.)

Я считаю, что хорошая практика должна быть как можно более точной при определении классов символов, которые должны быть повторены. Это помогает предотвратить catastrophic backtracking. Поэтому я бы использовал [^<]* вместо .*? с добавленным бонусом, который теперь обнаруживает бродячих персонажей после последнего тега. Этого не понадобится флаг re.DOTALL, так как [^<] действительно соответствует новой строке.

1
"</[^>]+?>[^<>]+?<" 

в IPython:

In [1]: a="<data> <tag>blar </tag><tagTwo> bo </tagTwo> some extra characters not enclosed that I want to remove <anothertag>bbb</anothertag></data>" 

In [2]: import re 

In [3]: re.sub("(</[^>]+?>)[^<>]+?<" ,"\\1<",a) 
Out[3]: '<data> <tag>blar </tag><tagTwo> bo </tagTwo><anothertag>bbb</anothertag></data>'