Можно ли получить текущий номер строки при разборе XML-документа с помощью Xerces?

У меня есть java-программа, которая анализирует XML-документ с помощью API xerces.

Мой класс синтаксического анализа расширяет org.apache.xerces.parsers.XMLDocumentParser, перегружая методы startElement, endElement, characters.

Поскольку это сложный XML-документ, написанный вручную (в основном это какие-то элементы конфигурации), классической проверки с помощью xsd или dtd недостаточно, и я должен сообщить пользователю, что XML-документ недействителен.

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

Я считаю, что это возможно, потому что исключения (org.apache.xerces.xni.parser.XMLParseException), сгенерированные анализатором, когда XML-документ не является допустимым XML, содержат эту информацию.


person chburd    schedule 20.02.2009    source источник


Ответы (2)


Я никогда не пробовал это с xerces, но парсеры SAX могут хранить SAX Locator, из которого вы можете получить номера строк и столбцов при анализе документа (или после исключения).

Похоже, XMLDocumentParser может сделать то же самое. Его родительский класс AbstractXMLDocumentParser имеет startDocument, который передается параметр XMLLocator. Если вы переопределите этот метод, вы можете сохранить XMLLocator и использовать его методы getLineNumber и getColumnNumber.

person Jason Day    schedule 20.02.2009
comment
переопределение метода startDocument - это способ пойти и отлично работать в моем случае, спасибо - person chburd; 23.02.2009

Не уверен, какой будет «правильный» способ, но посмотрите на API, предполагая, что вы предоставляете XMLInputSource, который принимает InputStream или Reader, который вы можете предоставить в InputStream / Reader, который заключен в LineNumberInputStream или LineNumberReader, а затем запрашивает его для строки номер.

eg:

InputStream stream;

stream = ...;

new XMLInputSource(stream);

станет:

InputStream stream;
LineNumberInputStream lineStream;

stream = ...;
lineStream = new LineNumberInputStream(lineStream);

new XMLInputSource(lineStream);

// can now ask the line stream what line it is on via getLineNumber()

Я предполагаю, что вам также нужно будет передать LineNumberInputStream / LineNumberReader вашему классу, который расширяет XMLDocumentParser.

Не уверен, что все это возможно в вашем коде.

Или покопайтесь в источнике и узнайте, как они это делают. Если переменные / методы, к которым вам нужен доступ, являются частными, и вы не беспокоитесь о том, что ваш код сломается в будущем, вы можете использовать отражение и удалить разрешения доступа, чтобы получить к нему доступ.

person TofuBeer    schedule 20.02.2009
comment
ваше решение было тем, что я имел в виду, если бы это было невозможно с помощью API. Я рад, что мне не нужно этого делать :-), но спасибо - person chburd; 23.02.2009
comment
Это не обязательно сработает. На самом деле, вероятно, не будет. Анализатор XML вполне мог прочитать несколько строк, прежде чем он потрудится сообщить какую-либо информацию в документе. Действительно, один тег может занимать несколько строк. LineNumberReader, скорее всего, не позиционируется там, где он должен быть, когда он должен быть там, чтобы это работало. :-( - person Elliotte Rusty Harold; 28.02.2017