Разбор XML в Ruby

Я использую синтаксический анализатор REXML Ruby для анализа файла XML. Но на 64-битном компьютере AIX с 64-битным Ruby я получаю следующую ошибку:

REXML::ParseException: #<REXML::ParseException: #<RegexpError: Stack overflow in 
regexp matcher: 
/^<((?>(?:[\w:][\-\w\d.]*:)?[\w:][\-\w\d.]*))\s*((?>\s+(?:[\w:][\-\w\d.]*:)?[\w:][\-\w\d.]*\s*=\s*(["']).*?\3)*)\s*(\/)?>/mu>

Призыв к тому же примерно такой:

REXML::Document.new(File.open(actual_file_name, "r"))

У кого-нибудь есть идеи относительно того, как решить эту проблему?


person Ricketyship    schedule 10.01.2012    source источник
comment
Это ваш зверь регулярного выражения или это из REXML?   -  person Niklas B.    schedule 10.01.2012
comment
Это из REXML. Это не регулярное выражение, которое я написал. Я просто использую REXML для анализа XML-документа   -  person Ricketyship    schedule 10.01.2012
comment
Итак, REXML дает этому зверю регулярное выражение: D   -  person Ricketyship    schedule 10.01.2012


Ответы (2)


У меня было несколько проблем с REXML, похоже, это не самая зрелая библиотека. Обычно я использую Nokogiri для синтаксического анализа Ruby XML, он должен быть быстрее и стабильнее, чем REXML. После установки с помощью sudo gem install nokogiri вы можете использовать что-то вроде этого, чтобы получить экземпляр DOM:

doc = Nokogiri.XML(File.open(actual_file_name, 'rb'))
# => #<Nokogiri::XML::Document:0xf1de34 name="document" [...] >

Документация на официальном веб-сайте также намного лучше, чем у REXML, ИМХО.

person Niklas B.    schedule 10.01.2012
comment
Я хочу знать, является ли это конкретной проблемой с рубиновой 64-битной версией. Та же проблема не воспроизводится на 32-битной коробке. И если есть обходной путь для того же, а не установка какой-либо другой библиотеки. - person Ricketyship; 10.01.2012
comment
@Bharath: Тогда лучше всего сообщить об этом в системе отслеживания ошибок Ruby. - person Niklas B.; 10.01.2012
comment
@Bharath: также вполне может быть, что ваш XML-файл просто слишком велик или слишком глубоко вложен. Возможно, вам следует попробовать какой-нибудь анализатор потока XML в этом случае. - person Niklas B.; 10.01.2012
comment
Тогда почему тот же файл анализируется в 32-битном рубине? В идеале, 64-битный ruby ​​должен быть способен выполнять все действия, выполняемые 32-битной библиотекой ruby. Дело в том, что 64-битная рубиновая версия имеет некоторые ограничения? Если да, то есть ли документация на него? - person Ricketyship; 10.01.2012
comment
@Barath: Нет, я скорее думаю, что это ошибка. Как я уже сказал, это меня не удивит, большинство людей уже какое-то время используют Nokogiri вместо REXML. - person Niklas B.; 10.01.2012
comment
Файл имеет всего двухуровневую вложенность. Сам файл весит около 54кб. Так что не совсем уверен, что вызывает эту проблему. - person Ricketyship; 10.01.2012
comment
Но у меня есть затаённое подозрение, что проблема специфична для aix box. В окне AIX я обнаружил следующую строку кода, вызывающую проблему: word_wrap(decode_field(column[:column_name], @name), line_width = 800) - person Ricketyship; 10.01.2012
comment
Возникала следующая ошибка: ActionView::TemplateError: слишком большой квантификатор в {,}: /(.{1,800})(\s+|$)/ ... когда я углубился в код ruby, я обнаружил, что word_wrap был используя соответствие регулярному выражению. Это было неудачно. даже на irb та же проблема сохранилась. Наконец, мне пришлось уменьшить количество повторений регулярного выражения, то есть значение {,}. Тогда это сработало. И самое главное, что это происходило на 32-битной машине AIX!!! Так что очевидно, где-то есть какое-то ограничение. - person Ricketyship; 10.01.2012

Почти сразу нашел ответ.

Первое, что я сделал, это поискал в исходном коде ruby ​​выдаваемую ошибку. Я обнаружил, что за это отвечает regex.h.

В regex.h поток кода выглядит примерно так:

/* Maximum number of duplicates an interval can allow.  */
#ifndef RE_DUP_MAX
#define RE_DUP_MAX  ((1 << 15) - 1)
#endif

Теперь проблема здесь RE_DUP_MAX. В AIX такая же константа определена где-то в /usr/include. Я искал его и нашел в

/usr/include/NLregexp.h
/usr/include/sys/limits.h
/usr/include/unistd.h

Я не уверен, какой из трех используется (скорее всего, NLregexp.h). В этих заголовках значение RE_DUP_MAX установлено равным 255! Таким образом, количество повторений регулярного выражения ограничено!

Короче говоря, причина в том, что компиляция принимает значение, определенное системой, чем то, которое мы определили в regex.h!

Это также отвечает на мой вопрос, который я недавно задал: Ограничение регулярных выражений в ruby ​​64 компиляция bit aix

Я не смог ответить на него сразу, так как мне нужно иметь минимум 100 репутации :D :D Ура!

person Community    schedule 19.01.2012