Схема XSD XML в Java

Схема XSD представляет собой более строгое, чем DTD, описание XML-документа. XSD-схема, в отличие от DTD, сама является XML-документом и поэтому более гибкая для использования в приложениях, задания правил документа, дальнейшего расширения новой функциональностью. В отличиеи от DTD, эта схема содержит много базовых типов (44 типа) и имеет поддержку пространств имен (namespace). С помощью схемы XSD можно также проверить документ на корректность.

Схема XSD первой строкой должна содержать декларацию XML

<?xml version="1.0" encoding="UTF-8"?>

Любая схема своим корневым элементом должна содержать элемент schema.

Для создания схемы нужно описать все элементы: их тип, количество повторений, дочерние элементы. Сам элемент создается элементом element, который может включать следующие атрибуты:

ref – ссылается на определение элемента, находящегося в другом месте;

name – определяет имя элемента;

type – указывает тип элемента;

minOccurs и maxOccurs – количество повторений этого элемента (по умолчанию 1), чтобы указать, что количество элементов неограниченно, в атрибуте maxOccurs нужно задать unbounded.

Если стандартные типы не подходят, можно создать свой собственный тип элемента. Типы элементов делятся на простые и сложные. Различия заключаются в том, что сложные типы могут содержать другие элементы, а простые – нет.

Простые типы

Элементы, которые не имеют атрибутов и дочерних элементов, называются простыми и должны иметь простой тип данных.

Существуют стандартные простые типы, например string (представляет строковое значение), boolean (логическое значение), integer (целое значение), float (значение с плавающей точкой), ID (идентификатор) и др. Также простые типы можно создавать на основе существующих типов посредством элемента simpleType. Атрибут name содержит имя типа.

Все типы в схеме могут быть объявлены как локально внутри элемента, так и глобально с использованием атрибута name для ccылки на тип в любом месте схемы. Для указания основного типа используется элемент restriction. Его атрибут base указывает основной тип. В элемент restriction можно включить ряд ограничений на значения типа:

minInclusive – определяет минимальное число, которое может быть значением этого типа;

maxInclusive – максимальное значение типа;

length – длина значения;

pattern – определяет шаблон значения;

enumeration – служит для создания перечисления.

Следующий пример описывает тип Login, производный от ID и отвечающий заданному шаблону в элементе pattern.

<simpleType name="Login">

<restriction base="ID">

<pattern value="[a-zA-Z]{3}[a-zA-Z0-9_]+"/>

</restriction>

</simpleType>

Сложные типы

Элементы, содержащие в себе атрибуты и/или дочерние элементы, называются сложными.

Сложные элементы создаются с помощью элемента complexType. Так же как и в простом типе, атрибут name задает имя типа. Для указания, что элементы должны располагаться в определенной последовательности, используется элемент sequence. Он может содержать элементы element, определяющие содержание сложного типа. Если тип может содержать не только элементы, но и текстовую информацию, необходимо задать значение атрибута mixed в true. Кроме элементов, тип может содержать атрибуты, которые создаются элементом

attribute. Атрибуты элемента attribute: name – имя атрибута, type – тип значения атрибута. Для указания, обязан ли использоваться атрибут, нужно использовать атрибут use, который принимает значения required, optional, prohibited. Для установки значения по умолчанию используется атрибут default , а для фиксированного значения – атрибут fixed.

Следующий пример демонстрирует описание типа Student:

<complexType name="Student">

<sequence>

<element name="name" type="string"/>

<element name="telephone" type="decimal"/>

<element name="address" type="tns:Address"/>

</sequence>

<attribute name="login" type="tns:Login"

use="required"/>

<attribute name="faculty" type="string"

use="required"/>

</complexType>

Для объявления атрибутов в элементах, которые могут содержать только текст, используются элемент simpleContent и элемент extension, с помощью которого расширяется базовый тип элемента атрибутом(ами).

<element name="Student">

<complexType>

<simpleContent>

<extension base="string">

<attribute name="birthday" type="string"/>

</extension>

</simpleContent>

</complexType>

</element>

Для расширения/ограничения ранее объявленных сложных типов используется элемент complexContent.

<complexType name=”personType”>

<sequence>

<element name=”firstName” type=”string”/>

<element name=”lastName” type=”string”/>

<element name=”address” type=”string”/>

</sequence>

</complexType>

<complexType name=”studentType”>

<complexContent>

<extension base=”personType”>

<sequence>

<element name=”course” type=”integer”/>

<element name=”faculty” type=”string”/>

</sequence>

</extesion>

</complexContent>

</complexType>

<element name=”Student” type=”studentType”/>

Для задания порядка следования элементов в XML используются такие теги, как <all>, который допускает любой порядок.

<element name=”person”>

<complexType>

<all>

<element name=”firstName” type=”string”/>

<element name=”lastName” type=”string”/>

</all>

</complexType>

</element>

Элемент <choice> указывает, что в XML может присутствовать только один из перечисленных элементов. Элемент <sequence> задает строгий порядок дочерних элементов.

Для списка студентов XML-схема students.xsd может выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>

<schema xmlns="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.example.com/Students"

xmlns:tns="http://www.example.com/Students">

<element name="students">

<complexType>

<sequence>

<element name="student" type="tns:Student" minOccurs="1" maxOccurs="unbounded" />

</sequence>

</complexType>

</element>

<complexType name="Student">

<sequence>

<element name="name" type="string" />

<element name="telephone" type="decimal" />

<element name="address" type="tns:Address" />

</sequence>

<attribute name="login" type="tns:Login" use="required" />

<attribute name="faculty" type="string" use="required" />

</complexType>

<simpleType name="Login">

<restriction base="ID">

<pattern value="[a-zA-Z]{3}[a-zA-Z0-9_]*"/>

</restriction>

</simpleType>

<complexType name="Address">

<sequence>

<element name="country" type="string" />

<element name="city" type="string" />

<element name="street" type="string" />

</sequence>

</complexType>

</schema>

В приведенном примере используется понятие пространства имен namespace. Пространство имен введено для разделения наборов элементов с соответствующими правилами, описанными схемой. Пространство имен объявляется с помощью атрибута xmlns и префикса, который используется для элементов из данного пространства.

Например, xmlns="http://www.w3.org/2001/XMLSchema" задает про­странство имен по умолчанию для элементов, атрибутов и типов схемы, которые принадлежат пространству имен "http://www.w3.org/2001/XMLSchema" и описаны соответствующей схемой.

Атрибут targetNamespace="http://www.example.com/Students" задает пространство имен для элементов/атрибутов, которые описывает данная схема.

Атрибут xmlns:tns="http://www.example.com/Students" вводит префикс для пространства имен (элементов) данной схемы. То есть для всех элементов, типов, описанных данной схемой и используемых здесь же требуется использовать префикс tns, как в случае с типами – tns:Address, tns:Login и т.д.

Действие пространства имён распространяется на элемент, где он объявлен, и на все дочерние элементы.

Тогда для проверки документа объекту-парсеру следует дать указание использовать DTD или схему XSD, и в XML-документ вместо ссылки на DTD добавить вместо корневого элемента <students> элемент <tns:students> вида:

<tns:students xmlns:tns="http://www.example.com/Students"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.example.com/Students students.xsd ">

Следующий пример выполняет проверку документа на корректность средствами языка Java.

/* пример # 13 : проверка корректности документа XML: XSDMain.java */

package chapt16.xsd;

import java.io.IOException;

import org.xml.sax.SAXException;

import org.apache.xerces.parsers.DOMParser;

import org.xml.sax.SAXNotRecognizedException;

import org.xml.sax.SAXNotSupportedException;

import chapt16.xsd.MyErrorHandler;

public class XSDMain {

public static void main(String[] args) {

String filename = "students.xml";

DOMParser parser = new DOMParser();

try {

// установка обработчика ошибок

parser.setErrorHandler(new MyErrorHandler("log.txt"));

// установка способов проверки с использованием XSD

parser.setFeature(

"http://xml.org/sax/features/validation", true);

parser.setFeature(

"http://apache.org/xml/features/validation/schema", true);

parser.parse(filename);

} catch (SAXNotRecognizedException e) {

e.printStackTrace();

System.out.print("идентификатор не распознан");

} catch (SAXNotSupportedException e) {

e.printStackTrace();

System.out.print("неподдерживаемая операция");

} catch (SAXException e) {

e.printStackTrace();

System.out.print("глобальная SAX ошибка ");

} catch (IOException e) {

e.printStackTrace();

System.out.print("ошибка I/O потока");

}

System.out.print("проверка " + filename + " завершена");

}

}

Класс обработчика ошибок может выглядеть следующим образом:

/* пример # 14 : обработчик ошибок :  MyErrorHandler.java */

package chapt16.xsd;

import java.io.IOException;

import org.xml.sax.ErrorHandler;

import org.xml.sax.SAXParseException;

import org.apache.log4j.FileAppender;

import org.apache.log4j.Logger;

import org.apache.log4j.SimpleLayout;

public class MyErrorHandler implements ErrorHandler {

private Logger logger;

public MyErrorHandler(String log) throws IOException {

//создание регистратора ошибок chapt16.xsd

logger = Logger.getLogger("chapt16.xsd");

//установка файла и формата вывода ошибок

logger.addAppender(new FileAppender(

new SimpleLayout(), log));

}

public void warning(SAXParseException e) {

logger.warn(getLineAddress(e) + "-" +

e.getMessage());

}

public void error(SAXParseException e) {

logger.error(getLineAddress(e) + " – "

+ e.getMessage());

}

public void fatalError(SAXParseException e) {

logger.fatal(getLineAddress(e) + " – "

+ e.getMessage());

}

private String getLineAddress(SAXParseException e) {

//определение строки и столбца ошибки

return e.getLineNumber() + " : "

+ e.getColumnNumber();

}

}

Чтобы убедиться в работоспособности кода, следует внести в исходный XML-документ ошибку. Например, сделать идентичными значения атрибута login. Тогда в результате запуска в файл будут выведены следующие сообщения обработчика об ошибках:

ERROR – 14 : 41 – cvc-id.2: There are multiple occurrences of ID value ‘mit’.

ERROR – 14 : 41 – cvc-attribute.3: The value ‘mit’ of attribute ‘login’ on element ‘student’ is not valid with respect to its type, ‘login’.

Если допустить синтаксическую ошибку в XML-документе, например, удалить закрывающую скобку в элементе telephone, будет выведено сообщение о фатальной ошибке:

FATAL – 7 : 26 – Element type "telephone2456474" must be followed by either attribute specifications, ">" or "/>".

В Java разработаны серьезные способы взаимодействия с XML. Начиная

с версии Java 6, эти механизмы включены в JDK.

Следующий пример на основе внутреннего класса создает структуру документа XML и сохраняет в ней объект.

/* пример # 15 : создание XML-документа на основе объекта:  DemoJSR.java */

package chapt16;

import java.io.*;

import javax.xml.bind.*;

import javax.xml.bind.annotation.*;

public class DemoJSR {

public static void main(String[] args) {

try {

JAXBContext context =

JAXBContext.newInstance(Student.class);

Marshaller m = context.createMarshaller();

Student s = new Student(1, "Bender");//объект

m.marshal(s, new FileOutputStream("stud.xml"));

} catch (FileNotFoundException e) {

System.out.println("XMl-файл не найден");

e.printStackTrace();

} catch (JAXBException e) {

System.out.println("JAXB-исключения");

e.printStackTrace();

}

}

@XmlRootElement

private static class Student {//внутренний класс

private int id;

private String name;

public Student() {

}

public Student(int id, String name) {

this.id = id;

this.name = name;

}

public int getID() {

return id;

}

public String getName() {

return name;

}

public void setID(int id) {

this.id = id;

}

public void setName(String name) {

this.name = name;

}

}

}

В результате компиляции и запуска программы будет создан XML-документ :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <student>

<ID>1</ID>

<name>Bender</name>

</student>

Возможно обратное создание на основе XML-схемы классов на языке Java:

/* пример # 16 : описание классов University, Course и перечисления Faculty в XSD-схеме:  student.xsd*/

<schema xmlns="http://www.w3c.org/2001/XMLSchema"

xmlns:Revealed="http://www.university.net"

targetNamespace="http://www.university.net">

<element name="University">

<complexType>

<sequence>

<element name="faculty" type="Revealed:Faculty"/>

<element name="course" type="Revealed:Course"/>

</sequence>

</complexType>

</element>

<complexType name="Course">

<sequence>

<element name="login" type="string"/>

<element name="name" type="string"/>

<element name="telephone" type="string"/>

</sequence>

</complexType>

<simpleType name="Faculty">

<restriction base="string">

<enumeration value="FPMI"></enumeration>

<enumeration value="MMF"></enumeration>

<enumeration value="Geo"></enumeration>

</restriction>

</simpleType>

</schema>

Запуск выполняется с помощью командной строки:

xjc student.xsd

В результате будет сгенерирован следующий код классов:

package net.university;

import javax.xml.bind.annotation.XmlEnum;

import javax.xml.bind.annotation.XmlEnumValue;

@XmlEnum

public enum Faculty {

FPMI("FPMI"),

MMF("MMF"),

@XmlEnumValue("Geo")

GEO_F("Geo");

private final String value;

Faculty(String v) {

value = v;

}

public String value() {

return value;

}

public static Faculty fromValue(String v) {

for (Faculty c: Faculty.values()) {

if (c.value.equals(v)) {

return c;

}

}

throw new IllegalArgumentException(v.toString());

}

}

package net.university;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlType;

/**

* <p>Java class for Course complex type.

*/

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "Course", propOrder = {

"login",

"name",

"telephone"

})

public class Course {

@XmlElement(required = true)

protected String login;

@XmlElement(required = true)

protected String name;

@XmlElement(required = true)

protected String telephone;

public String getLogin() {

return login;

}

public void setLogin(String value) {

this.login = value;

}

public String getName() {

return name;

}

public void setName(String value) {

this.name = value;

}

public String getTelephone() {

return telephone;

}

public void setTelephone(String value) {

this.telephone = value;

}

}

package net.university;

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

import javax.xml.bind.annotation.XmlType;

/**

* <p>Java class for anonymous complex type.

*/

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "", propOrder = {

"faculty",

"course"

})

@XmlRootElement(name = "University")

public class University {

@XmlElement(required = true)

protected Faculty faculty;

@XmlElement(required = true)

protected Course course;

public Faculty getFaculty() {

return faculty;

}

public void setFaculty(Faculty value) {

this.faculty = value;

}

public Course getCourse() {

return course;

}

public void setCourse(Course value) {

this.course = value;

}

}

package net.university;

import javax.xml.bind.annotation.XmlRegistry;

@XmlRegistry

public class ObjectFactory {

public ObjectFactory() {

}

public Course createCourse() {

return new Course();

}

public University createUniversity() {

return new University();

}

}

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100