2015-03-07 2 views
4

Я имею дело с искаженным XML в perl, который генерируется восходящим процессом, который я не могу изменить (похоже, это общая проблема здесь). Однако, насколько я видел, то XML имеет неправильный формат только один определенным образом: он имеет значения, которые содержат Unescaped атрибут менее чем знаки, например:Работа с неправильным XML

<tag v="< 2"> 

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

Похоже, что у меня есть два общих варианта:

  1. Fix входной XML, прежде чем я разобрать его, возможно, с использованием регулярных выражений.
  2. Найдите более прощающий синтаксический анализатор XML.

Я склоняюсь к варианту 1, так как хотел бы уловить любые другие ошибки в XML. Чтобы вы посоветовали? Если # 1, может ли кто-нибудь вести меня через подход регулярного выражения?

+0

Is неэкранированный '<' всегда следует пробел? – choroba

+0

Похоже не всегда. Это также не всегда первый символ после «.Это может быть что-то вроде v =« 3 <2 » – disruptiveglow

+0

Тег не может начинаться с пробела или числа. Возможно ли иметь' v = "a choroba

ответ

7

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

Ниже приведен быстрый, неэффективный сценарий проверки подлинности с использованием XML::Twig, потому что я до сих пор не понял, как построить & установить libxml2 с нуля на Windows.

#!/usr/bin/env perl 

use strict; 
use warnings; 

use XML::Twig; 

my $xml = q{ <tag v="< 2"/> }; 

while (1) { 
    eval { 
     my $twig = XML::Twig->new(
      twig_handlers => { tag => \&tag_handler }, 
     ); 
     $twig->parse($xml); 
     1; 
    } and last; 

    my $err = [email protected]; 

    my ($i) = ($err =~ /byte ([0-9]+)/) 
     or die $err; 

    substr($xml, $i, 1) eq '<' 
     or die $err; 
    $xml = substr($xml, 0, $i) . '&lt;' . substr($xml, $i + 1); 
} 

sub tag_handler { 
    my (undef, $elt) = @_; 
    print $elt->att('v'), "\n"; 
} 

Я написал несколько слов об этом on my blog.

+0

. Я, вероятно, продолжу рассказывать о том, как вы не пытаетесь исправить XML, но, как я уверен, мы оба знаем - это не всегда варианты в реальном мире. Мне очень нравится ваш подход к синтаксическому анализу, когда «просто сказать« нет »не вариант. – Sobrique

+0

Почему эти искаженные xml-файлы существуют? Можно ли исправить программы, которые сгенерировали эти XML-файлы? – xwang

7

Я знаю, что это не тот ответ, который вы хотите - но спецификация XML довольно ясна и строгая.

Малоформатный XML является фатальным.

Если это не работает в валидаторе, то ваш код не должен даже пытаться «исправить» его, не более того, чем вы попытаетесь автоматически «исправить» какой-либо программный код.

От Anotated XML Specification:

фатальная ошибка [Определение:] Ошибка которой соответствующий процессор XML должен обнаружить и сообщить приложению. После столкновения с фатальной ошибкой процессор может продолжить обработку данных для поиска дальнейших ошибок и может сообщать о таких ошибках приложению. Чтобы поддерживать коррекцию ошибок, процессор может делать необработанные данные из документа (с перемешанными символьными данными и разметкой), доступными для приложения. Однако, если обнаружена фатальная ошибка, процессор не должен продолжать нормальную обработку (т. Е. Он не должен продолжать передавать персональные данные и информацию о логической структуре документа в приложение обычным способом).

И конкретно в комментарии о том, почему: "Draconian" error-handling

Мы хотим XML, чтобы расширить возможности программистов писать код, который может быть передан через Интернет и выполнять на большом количестве компьютеров.Однако, если этот код должен включать обработку ошибок для всех видов неаккуратных практик конечных пользователей, он по необходимости должен иметь размер шара до такой степени, что он, например Netscape Navigator или Microsoft Internet Explorer, имеет размер в десятки мегабайт, побеждая цель.

Если вы когда-либо пытались собрать парсер HTML, вы поймете, почему это должно быть так - вы в конечном итоге писать СТОЛЬКИХ обработчик для особых случаев, плохие теги вложений, закрытие неявного тега что ваш код является беспорядком с самого начала.

И потому, что это моя любимая запись на переполнение стека - вот пример того, почему: RegEx match open tags except XHTML self-contained tags

Теперь я ценю это не всегда вариант, и вы, вероятно, не придет сюда, если спрашивать ваш вверх по течению " исправить ваш XML "был путь наименьшего сопротивления. Однако я бы все же настоятельно рекомендовал вам сообщать об этом как о дефекте в приложении для создания XML и как можно больше сопротивляться давлению, чтобы «исправить» программно, потому что, как вы правильно поняли, он создает себе мир боли, когда справа Ответ «Исправить проблему у источника».

Если вы действительно застряли на этой дороге, вы можете - как указывает Sinan Ünür - ваш единственный вариант - это ловушка, в которой вы парсер не сработали, а затем осмотрите и попробуйте отремонтировать, как вы идете. Но вы не найдете синтаксический анализатор XML, который сделает это за вас, потому что тот, который делает, - по определению.

Я бы предложить что сначала:

  • выкопать копия спецификации, чтобы показать тому, кто попросил вас сделать это.
  • указывают на то, что вся причина, по которой мы имеем стандарты, заключается в содействии интероперабельности.
  • Поэтому, делая что-то, что преднамеренно нарушает стандарт, вы рискуете бизнесом - вы создаете код, который может однажды загадочно сломаться, потому что использование таких вещей, как регулярные выражения или автоматическая фиксация, строится в виде набора предположений это может не совпадать.
  • Полезная концепция здесь technical debt - объясните, что вы несете технический долг за счет автоматической фиксации, для чего-то, что действительно не является вашей проблемой.
  • Затем спросите их, хотят ли они принять этот риск.
  • Если они думают, что это приемлемый риск, то просто продолжайте с ним - вы можете счесть это достойным внимания - игнорируя тот факт, что ваши исходные данные выглядят как XML и обрабатывают его так, как если бы это был обычный текст - используйте регулярные выражения для извлечения соответствующих строк данных и т. д.
  • Приведите извинения в комментариях к вашему будущему программисту по обслуживанию, объяснив, кто принял решение и почему.

Также может быть полезным в качестве ориентира: Which character should not be set as values in XML file

+0

Будучи на позициях, где казалось невозможным изменить поведение вверх по течению, я сочувствовал ситуации с ОП. Ваша точка зрения, очевидно, правильная и проголосовала за ваш ответ. –

+1

Я думаю, что мы все были там - я не собираюсь осуждать кого-либо за необоснованного начальника;) – Sobrique

+3

Иногда (и часто, я думаю), это не ваша сторона, это необоснованно. Вы застряли в том, что предоставляет безликая организация. –

Смежные вопросы