Spec-Zone .ru
спецификации, руководства, описания, API
|
Пример программы SAXLocalNameCount использует синтаксический анализатор непроверки допустимости по умолчанию, но это может также активировать проверку допустимости. Активирование проверки допустимости позволяет приложению говорить, содержит ли XML-документ правильные теги или являются ли те теги в правильной последовательности. Другими словами это может сказать Вам, допустим ли документ. Если проверка допустимости не активируется, однако, она может только сказать, правильно построен ли документ, как был показан в предыдущем разделе, когда Вы удалили закрывающий тэг из элемента XML. Для проверки допустимости, чтобы быть возможным, XML-документ должен быть связан с DTD или XML-схемой. Обе опции возможны с программой SAXLocalNameCount.
Если никакая другая фабрика, class определяется, значение по умолчанию SAXParserFactory class, не используется. Чтобы использовать синтаксический анализатор от различного производителя, можно изменить значение переменной окружения, которая указывает на него. Можно сделать это из командной строки:
java -Djavax.xml.parsers.SAXParserFactory=yourFactoryHere [...]
Имя фабрики, которое Вы определяете, должно быть полностью определенным именем class (все включенные префиксы пакета). Для получения дополнительной информации см. документацию в методе newInstance() SAXParserFactory class.
Вплоть до этой точки этот урок сконцентрировался на синтаксическом анализаторе непроверки допустимости. Этот раздел исследует синтаксический анализатор проверки допустимости, чтобы узнать то, что происходит, когда Вы используете это, чтобы проанализировать пример программы.
Две вещи должны быть поняты о синтаксическом анализаторе проверки допустимости:
Схема или DTD требуются.
Поскольку схема или DTD присутствуют, метод ContentHandler.ignorableWhitespace() вызывается когда бы ни было возможно.
Когда DTD будет присутствовать, синтаксический анализатор больше не будет вызывать метод characters() на пробеле, который это знает, чтобы быть не важным. С точки зрения приложения, которое интересуется обработкой только данных XML, который является хорошей вещью, потому что приложение никогда не беспокоится пробелом, который существует просто, чтобы сделать XML-файл читаемым.
С другой стороны, если Вы пишете приложение, которое фильтрует файл данных XML и если бы Вы хотите вывести одинаково читаемую версию файла, тогда тот пробел больше не был бы не важен: это было бы важно. Чтобы получить те символы, Вы добавили бы метод ignorableWhitespace к своему приложению. Чтобы обработать любой (обычно) игнорируемый пробел, который видит синтаксический анализатор, Вы должны были бы добавить что-то как следующий код, чтобы реализовать обработчик событий ignorableWhitespace.
public void ignorableWhitespace (char buf[], int start, int length) throws SAXException { emit("IGNORABLE"); }
Этот код просто генерирует сообщение, чтобы сообщить, что игнорируемый пробел был замечен. Однако, не все синтаксические анализаторы создаются равные. Спецификация SAX не требует, чтобы этот метод был вызван. Реализация XML Java делает так всякий раз, когда DTD позволяет.
SAXParserFactory должен быть установлен так, что, он использует синтаксический анализатор проверки допустимости вместо синтаксического анализатора непроверки допустимости значения по умолчанию. Следующий код от метода main() SAXLocalNameCount в качестве примера показывает, как сконфигурировать фабрику так, чтобы это реализовало синтаксический анализатор проверки допустимости.
static public void main(String[] args) throws Exception { String filename = null; boolean dtdValidate = false; boolean xsdValidate = false; String schemaSource = null; for (int i = 0; i < args.length; i++) { if (args[i].equals("-dtd")) { dtdValidate = true; } else if (args[i].equals("-xsd")) { xsdValidate = true; } else if (args[i].equals("-xsdss")) { if (i == args.length - 1) { usage(); } xsdValidate = true; schemaSource = args[++i]; } else if (args[i].equals("-usage")) { usage(); } else if (args[i].equals("-help")) { usage(); } else { filename = args[i]; if (i != args.length - 1) { usage(); } } } if (filename == null) { usage(); } SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setValidating(dtdValidate || xsdValidate); SAXParser saxParser = spf.newSAXParser(); // ... }
Здесь, программа SAXLocalNameCount конфигурируется, чтобы взять дополнительные параметры, когда она запускается, которые говорят ей не реализовывать проверку допустимости, проверку допустимости DTD, Определение XML-схемы (XSD) проверка допустимости, или проверка допустимости XSD против определенного исходного файла схемы. (Описания этих опций, -dtd, -xsd, и -xsdss также добавляются к методу usage(), но не показываются здесь.) Затем, фабрика конфигурируется так, чтобы она произвела соответствующий синтаксический анализатор проверки допустимости, когда newSAXParser будет вызван. Как замечено в Установке Синтаксического анализатора, можно также использовать setNamespaceAware(true), чтобы сконфигурировать фабрику, чтобы возвратить осведомленный о пространстве имен синтаксический анализатор. Реализация Sun поддерживает любую комбинацию параметров конфигурации. (Если комбинация не поддерживается определенной реализацией, она обязана генерировать ошибку конфигурации фабрики).
Хотя полная обработка XML-схемы выходит за рамки этого учебного руководства, этот раздел показывает Вам шаги, которые Вы делаете, чтобы проверить XML-документа, используя существующую схему, записанную на языке XML-схемы. Чтобы узнать больше о XML-схеме, можно рассмотреть онлайновое учебное руководство, Часть 0 XML-схемы: Учебник для начинающих, в http://www.w3.org/TR/xmlschema-0/.
Отметьте - есть многократные языки определения схемы, включая ОСЛАБЛЯЮТ НАНОГРАММ, Schematron, и стандарт "XML-схемы" W3C. (Даже DTD квалифицирует как "схема," хотя это - единственный, который не использует синтаксис XML, чтобы описать ограничения схемы.) Однако, "XML-схема" дарит нам проблему терминологии. Хотя фраза "схема XML-схемы" была бы точна, мы будем использовать фразу "определение XML-схемы", чтобы избежать появления избыточности.
Чтобы быть уведомленной относительно ошибок проверки допустимости в XML-документе, фабрика синтаксического анализатора должна быть сконфигурирована, чтобы создать синтаксический анализатор проверки допустимости, как показано в предыдущем разделе. Кроме того, следующее должно быть истиной:
Полезно запуститься, определяя константы, которые Вы будете использовать, устанавливая свойства. Пример SAXLocalNameCount устанавливает следующие константы.
public class SAXLocalNameCount extends DefaultHandler { static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; }
Отметьте - фабрика синтаксического анализатора должна быть сконфигурирована, чтобы генерировать синтаксический анализатор, который осведомлен о пространстве имен так же как проверяющий. Это показали в Конфигурировании Фабрики. Больше информации о пространствах имен предоставляется в
Затем следует сконфигурировать синтаксический анализатор, чтобы сказать это который язык схемы использовать. В SAXLocalNameCount проверка допустимости может быть выполнена или против DTD или против XML-схемы. Следующий код использует константы, определенные выше, чтобы определить язык XML-схемы W3C как тот, чтобы использовать, если опция -xsd определяется, когда программа запускается.
// ... if (xsdValidate) { saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); // ... }
В дополнение к обработке ошибок, описанной в Установке Обработки ошибок, есть одна ошибка, которая может произойти, конфигурируя синтаксический анализатор для основанной на схеме проверки допустимости. Если синтаксический анализатор не совместим с версией 1.2 JAXP или позже, и поэтому не поддерживает XML-схему, это может бросить SAXNotRecognizedException. Чтобы обработать тот случай, оператор setProperty() обертывается в блок попытки/выгоды, как показано в код ниже.
// ... if (xsdValidate) { try { saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); } catch (SAXNotRecognizedException x){ System.err.println("Error: JAXP SAXParser property not recognized: " + JAXP_SCHEMA_LANGUAGE); System.err.println( "Check to see if parser conforms to JAXP 1.2 spec."); System.exit(1); } } // ...
Чтобы проверить данных, используя определение XML-схемы, необходимо гарантировать, что XML-документ связывается с одним. Есть два способа сделать это.
Отметьте - Когда приложение определяет схему, чтобы использовать, это переопределяет любое объявление схемы в документе.
Чтобы определить определение схемы в документе, Вы создали бы XML, такой как это:
<documentRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='YourSchemaDefinition.xsd'>
Первый атрибут определяет пространство имен XML (xmlns) префикс, xsi, который обозначает экземпляр XML-схемы. Вторая строка определяет схему, чтобы использовать для элементов в документе, у которых нет префикса пространства имен, а именно, для элементов, которые обычно определяются в любом простом, несложном XML-документе.
Отметьте - Больше информации о пространствах имен включается в Проверку допустимости с XML-схемой в Объектной модели документа. Пока, думайте об этих атрибутах как о "волшебном колдовстве", Вы используете, чтобы проверить простого XML-файла, который не использует их. После того, как Вы узнали больше о пространствах имен, Вы будете видеть, как использовать XML-схему, чтобы проверить составных документов, которые действительно используют их. Те идеи обсуждаются в Проверке допустимости с Многократными Пространствами имен в Объектной модели документа.
Можно также определить файл схемы в приложении, как имеет место в SAXLocalNameCount.
// ... if (schemaSource != null) { saxParser.setProperty(JAXP_SCHEMA_SOURCE, new File(schemaSource)); } // ...
В коде выше, переменный schemaSource касается исходного файла схемы, на который можно указать на приложение SAXLocalNameCount, запуская это с опции -xsdss и обеспечивая имя исходного файла схемы, который будет использоваться.
Важно распознать, что единственная причина, исключение выдается, когда файл приводит проверку допустимости к сбою, в результате кода обработки ошибок, показанного в Установке Обработки ошибок. Тот код воспроизводится здесь как напоминание:
// ... public void warning(SAXParseException spe) throws SAXException { out.println("Warning: " + getParseExceptionInfo(spe)); } public void error(SAXParseException spe) throws SAXException { String message = "Error: " + getParseExceptionInfo(spe); throw new SAXException(message); } public void fatalError(SAXParseException spe) throws SAXException { String message = "Fatal Error: " + getParseExceptionInfo(spe); throw new SAXException(message); } // ...
Если эти исключения не выдаются, ошибки проверки допустимости просто игнорируются. Вообще, ошибка парсинга SAX является ошибкой проверки допустимости, хотя она может также быть сгенерирована, если файл определяет версию XML, который синтаксический анализатор не готовится обработать. Помните, что Ваше приложение не будет генерировать исключение проверки допустимости, если Вы не предоставите обработчик ошибок, такой как тот здесь.
Как отмечалось ранее предупреждения сгенерированы только, когда синтаксический анализатор SAX обрабатывает DTD. Некоторые предупреждения сгенерированы только синтаксическим анализатором проверки допустимости. Основная цель синтаксического анализатора непроверки допустимости состоит в том, чтобы работать настолько быстро насколько возможно, но она также генерирует некоторые предупреждения.
Спецификация XML предлагает, чтобы предупреждения были сгенерированы в результате следующего:
Обеспечение дополнительных объявлений для объектов, атрибутов, или нотаций. (Такие объявления игнорируются. Только первое используется. Кроме того, отметьте, что двойные определения элементов всегда производят фатальную ошибку, проверяя, как Вы видели ранее.)
Ссылка на необъявленный тип элемента. (Ошибка законности происходит, только если необъявленный тип фактически используется в XML-документе. Предупреждение заканчивается, когда на необъявленный элемент ссылаются в DTD.)
Объявление атрибутов для необъявленных типов элемента.
Синтаксический анализатор SAX XML Java также испускает предупреждения в других случаях:
Никакой <!DOCTYPE ...>, проверяя.
Ссылки на неопределенный объект параметра, если не проверяющий. (Проверяя, ошибка заканчивается. Хотя непроверяющие синтаксические анализаторы не обязаны читать объекты параметра, синтаксический анализатор XML Java делает так. Поскольку это не требование, синтаксический анализатор XML Java генерирует предупреждение, а не ошибку.)
Определенные случаи, где объявление кодировки символов не выглядит правильным.
В этом разделе пример программы SAXLocalNameCount, используемый ранее, будет использоваться снова, кроме этого времени, это будет выполнено с проверкой допустимости против XML-схемы или DTD. Лучший способ демонстрировать различные типы проверки допустимости состоит в том, чтобы изменить код XML-файла, проанализированного, так же как связанная схема и DTD, чтобы повредить обработку и заставить приложение генерировать исключения.
Как указано выше эти примеры снова используют программу SAXLocalNameCount. Расположения, где Вы найдете выборку и ее связанные файлы, даются в Выполнении Примера Синтаксического анализатора SAX без Проверки допустимости.
% cd install-dir/jaxp-1_4_2-release-date/samples
% javac sax/*
Это - тот же самый XML-файл, который был обработан без проверки допустимости в Выполнить Пример SAXLocalNameCount без Проверки допустимости. В начале data/rich_iii.xml Вы будете видеть что места объявления DOCTYPE синтаксический анализатор проверки допустимости к файлу DTD под названием play.dtd. Если проверка допустимости DTD будет активирована, то структура проанализированного XML-файла будет проверена по структуре, обеспеченной в play.dtd.
Не забывайте сохранять модификацию, но оставлять файл открытым, поскольку это будет необходимо снова позже.
Чтобы сделать это, следует определить опцию -dtd, когда Вы выполняете программу.
% java sax/SAXLocalNameCount -dtd data/rich_iii.xml
Результат, который Вы видите, будет выглядеть примерно так:
Exception in thread "main" org.xml.sax.SAXException: Error: URI=file:install-dir/JAXP_sources/jaxp-1_4_2-release-date /samples/data/rich_iii.xml Line=12: Document is invalid: no grammar found.
Отметьте - Это сообщение было сгенерировано JAXP 1.4.2 библиотеки. Если Вы будете использовать различный синтаксический анализатор, то сообщение об ошибке, вероятно, будет несколько отличаться.
Это сообщение говорит, что нет никакой грамматики, против которой документ может быть проверен rich_iii.txt, так поэтому это автоматически недопустимо. Другими словами сообщение говорит, что Вы пытаетесь проверить документа, но никакой DTD не был объявлен, потому что никакое объявление DOCTYPE не присутствует. Так теперь Вы знаете, что DTD является требованием для допустимого документа. Это имеет смысл.
Снова, не забывайте сохранить файл, но оставить его открытым.
Измените запуск и конечные тэги от <PERSONA> и </PERSONA> к <PERSON> и </PERSON>. Строка 26 должна теперь быть похожей на это:
26:<PERSON>KING EDWARD The Fourth</PERSON>
Снова, не забывайте сохранять модификацию, и оставлять файл открытым.
На сей раз Вы будете видеть различную ошибку, когда Вы выполните программу:
% java sax/SAXLocalNameCount -dtd data/rich_iii.xml Exception in thread "main" org.xml.sax.SAXException: Error: URI=file:install-dir/JAXP_sources/jaxp-1_4_2-release-date /samples/data/rich_iii.xml Line=26: Element type "PERSON" must be declared.
Здесь можно видеть, что синтаксический анализатор возразил против элемента, который не включается в DTD data/play.dtd.
Возвратите запуск и конечные тэги к их оригинальным версиям, <PERSONA> и </PERSONA>.
Еще раз не забывайте сохранять модификацию.
Как прежде, Вы будете видеть другую ошибку проверки допустимости:
java sax/SAXLocalNameCount -dtd data/rich_iii.xml Exception in thread "main" org.xml.sax.SAXException: Error: URI=file:install-dir/JAXP_sources/jaxp-1_4_2-release-date /samples/data/rich_iii.xml Line=85: The content of element type "PERSONAE" must match "(TITLE,(PERSONA|PGROUP)+)".
Удаляя элемент <TITLE> из строки 24, элемент <PERSONAE> представляется недопустимый, потому что это не содержит подэлементы, которые DTD ожидает элемента <PERSONAE>. Отметьте, что сообщение об ошибке утверждает, что ошибка в гармонии 85 из data/rich_iii.xml, даже при том, что Вы удалили элемент <TITLE> из строки 24. Это - то, потому что закрывающий тэг элемента <PERSONAE> располагается в строке 85, и синтаксический анализатор только выдает исключение, когда это достигает конца элемента это парсинг.
В файле DTD можно видеть объявление элемента <PERSONAE>, так же как всех других элементов, которые могут использоваться в XML-документах, которые соответствуют DTD игры. Объявление <PERSONAE> похоже на это.
<!ELEMENT PERSONAE (TITLE, (PERSONA | PGROUP)+)>
Как можно видеть, элемент <PERSONAE> требует подэлемента <TITLE>. Канал (|), ключ означает, что или <PERSONA> или подэлементы <PGROUP> могут быть включены в элемент <PERSONAE>, и плюс (+) ключ после группировки (PERSONA | PGROUP), означает, что по крайней мере один или больше любой из этих подэлементов должны быть включены.
Добавление вопросительного знака к объявлению подэлемента в DTD делает присутствие одного экземпляра того подэлемента дополнительным.
<!ELEMENT PERSONAE (TITLE?, (PERSONA | PGROUP)+)>
Если Вы были, добавляет звездочка (*) после элемента, Вы могли бы включать или нулевые или многократные экземпляры того подэлемента. Однако, в этом случае не имеет смысла иметь больше чем один title в разделе документа.
Не забывайте сохранять модификацию, которую Вы сделали к data/play.dtd.
% java sax/SAXLocalNameCount -dtd data/rich_iii.xml
На сей раз следует видеть надлежащий вывод SAXLocalNameCount без ошибок.
Предыдущее осуществление, демонстрируемое, используя SAXLocalNameCount, чтобы проверить XML-файла против DTD. В этом осуществлении Вы будете использовать SAXLocalNameCount, чтобы проверить различного XML-файла и против стандартного определения XML-схемы и против пользовательского исходного файла схемы. Снова, этот тип проверки допустимости будет демонстрироваться, повреждая процесс парсинга, изменяя XML-файл и схему, так, чтобы синтаксический анализатор бросил ошибки.
Как указано выше эти примеры снова используют программу SAXLocalNameCount. Расположения, где Вы найдете выборку и ее связанные файлы, даются в Выполнении Примера Синтаксического анализатора SAX без Проверки допустимости.
% cd install-dir/jaxp-1_4_2-release-date/samples
% javac sax/*
Это - простой XML-файл, который обеспечивает имена и контактную информацию для сотрудников небольшой компании. В этом XML-файле Вы будете видеть, что он был связан с файлом определения схемы personal.xsd.
<personnel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='personal.xsd'>
Эта схема определяет, какие виды информации требуются о каждом сотруднике для XML-документа, связанного со схемой считаться допустимыми. Например, исследуя определение схемы, можно видеть, что каждый элемент person требует name, и что каждое имя человека должно включить имя family и имя given. У сотрудников могут также дополнительно быть адреса электронной почты и URL.
Объявление элемента email теперь следующие.
<xs:element ref="email" minOccurs='1' maxOccurs='unbounded'/>
Рабочий Каждый теперь похож на это:
<person id="one.worker"> <name><family>Worker</family> <given>One</given></name> <link manager="Big.Boss"/> </person>
% java sax/SAXLocalNameCount data/personal-schema.xml
SAXLocalNameCount сообщает Вам о числе раз, каждый элемент происходит в personal-schema.xml.
Local Name "email" occurs 5 times Local Name "name" occurs 6 times Local Name "person" occurs 6 times Local Name "family" occurs 6 times Local Name "link" occurs 6 times Local Name "personnel" occurs 1 times Local Name "given" occurs 6 times
Вы видите, что email только происходит пять раз, тогда как есть шесть элементов person в personal-schema.xml. Так, потому что мы устанавливаем минимальные возникновения элемента email к 1 на элемент person, мы знаем, что этот документ недопустим. Однако, потому что SAXLocalNameCount не сказали проверить против схемы, ни о какой ошибке не сообщают.
Как Вы видели в Проверке допустимости с XML-схемой выше, у SAXLocalNameCount есть опция, чтобы включить проверке допустимости схемы. Выполните SAXLocalNameCount со следующей командой.
% java sax/SAXLocalNameCount -xsd data/personal-schema.xml
На сей раз Вы будете видеть следующее сообщение об ошибке.
Exception in thread "main" org.xml.sax.SAXException: Error: URI=file:install_dir/samples/data/personal-schema.xml Line=19: cvc-complex-type.2.4.a: Invalid content was found starting with element 'link'. One of '{email}' is expected.
% java sax/SAXLocalNameCount -xsd data/personal-schema.xml
На сей раз Вы будете видеть корректный вывод без ошибок.
Удалите курсивный код из элемента personnel.
<personnel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='personal.xsd'/>
% java sax/SAXLocalNameCount -xsd data/personal-schema.xml
Очевидно, это не будет работать, поскольку определение схемы, против которого можно проверить XML-файла, не было объявлено. Вы будете видеть следующую ошибку.
Exception in thread "main" org.xml.sax.SAXException: Error: URI=file:install_dir/samples/data/personal-schema.xml Line=8: cvc-elt.1: Cannot find the declaration of element 'personnel'.
% java sax/SAXLocalNameCount -xsdss data/personal.xsd data/personal-schema.xml
На сей раз Вы используете опцию SAXLocalNameCount, которая позволяет Вам определять определение схемы, которое не трудно кодируется в приложение. Следует видеть корректный вывод.