Створення класів Java з файлів .XSD…?


127

У мене є гігантський файл схеми SDK .XSD QuickBooks, який визначає XML запити / відповіді, які я можу надсилати / отримувати з QuickBooks.

Мені б хотілося легко створювати класи Java з цих .XSD-файлів, які потім я міг би використовувати для маршалки XML до об'єктів Java, а Java-об'єктів до XML.

Чи є простий спосіб зробити це ...?

В ідеалі, вона не вимагає ніяких бібліотек, що знаходяться поза базовим дистрибутивом Java під час виконання. Але я гнучка ...


6
Якщо ви хочете створити вручну, помістіть .xsd-файл у проект затемнення, клацніть правою кнопкою миші на файл, а потім натисніть «Створити»
Junchen Liu

Відповіді:


121

JAXB робить саме те, що ви хочете. Він вбудований в JRE / JDK починаючи з 1.6


7
На жаль, ця функція більше не буде доступною для Java 9. Це тому, що залучені класи (зокрема, класи com.sun.tools.xjc. *) Більше не будуть доступні через JDK.
Марко

4
Я не думаю, що видалення цього з JDK не повинно бути проблемою, тому що проект java.net (пов'язаний у відповіді), ймовірно, залишиться.
stmoebius

1
Як пояснено тут , ви можете додати залежності в Java 9 аргументом командного рядка або додати залежність вручну.
Маттіас Ронге

118

Щоб розширити коментарі "використовувати JAXB" вище,

У Windows "%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd

наприклад, "%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Почекайте трохи, і якщо у вас був добре сформований XSD файл, ви отримаєте кілька добре сформованих Java-класів


3
Щиро дякую! Для генерації класів вищого рівня, а не інкапсульованих див.: Stackoverflow.com/questions/13175224/… . І якщо це призводить до конфліктів імен класу, дивіться: stackoverflow.com/questions/13414407/…
завтра,

38

Якщо ви хочете розпочати кодування Java в XML та XML на Java менше ніж за 5 хвилин, спробуйте просту серіалізацію XML. Не витрачайте години на вивчення API JAXB http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

Однак, якщо ви дуже зацікавлені у вивченні JAXB, ось вам чудовий підручник http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml

Зміст навчального посібника:

JAXB для простої серіалізації Java-XML

Існує ряд способів зробити XML-серіалізацію на Java. Якщо ви хочете тонко контролювати синтаксичний аналіз і серіалізацію, ви можете перейти на SAX, DOM або Stax для кращої продуктивності. Однак мені часто хочеться зробити просте відображення POJO та XML. Однак створення класів Java для розбору подій XML вручну не є тривіальним. Нещодавно я виявив, що JAXB - це швидке та зручне картографування чи серіалізація Java-XML.

JAXB містить безліч корисних функцій, тут можна ознайомитися з реалізацією посилань. Блог Kohsuke - це також хороший ресурс, щоб дізнатися більше про JAXB. Для цього запису в блозі я покажу вам, як зробити просту серіалізацію Java-XML за допомогою JAXB.

POJO до XML

Скажімо, у мене є об'єкт Java-предмет. Я хочу серіалізувати об’єкт Item у формат XML. Перше, що я повинен зробити, це анотувати цей POJO за допомогою декількох приміток XML від пакета javax.xml.bind.annotation. * Див. Перелік коду 1 для Item.java

З коду

  • @XmlRootElement(name="Item") вказує на те, що я хочу бути кореневим елементом.
  • @XmlType(propOrder = {"name", "price"}) вказує на порядок того, що я хочу, щоб елемент був розташований у висновку XML.
  • @XmlAttribute(name="id", ...) вказує, що id - атрибут кореневого елемента.
  • @XmlElement(....) вказує на те, що я хочу, щоб ціна та назва були елементами в позиції.

Моя Item.javaготова. Тоді я можу йти вперед і створити сценарій JAXB для маршалінгу елемента.

//creating Item data object
Item item = new Item();
item.setId(2);
item.setName("Foo");
item.setPrice(200);
.....

JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
//I want to save the output file to item.xml
marshaller.marshal(item, new FileWriter("item.xml"));

Повний перелік кодів див. У списку кодів 2 main.java. item.xmlСтворюється вихідний файл з переліком коду 3 . Це виглядає приблизно так:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.sun.com/teera/ns/item">

 <ns1:itemName>Foo</ns1:itemName>
<ns1:price>200</ns1:price>

</ns1:item>

Легко так? Ви можете альтернативно каналізувати вихідний XML у вигляді текстового рядка, потоку, Writer, ContentHandler тощо, просто змінивши параметр методу маршала (...), наприклад

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
// save xml output to the OutputStream instance
marshaller.marshal(item, <java.io.OutputStream instance>);

...
JAXBContext context = JAXBContext.newInstance(item.getClass());
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
//save to StringWriter, you can then call sw.toString() to get java.lang.String
marshaller.marshal(item, sw);

XML в POJO

Давайте повернемо процес. Припустимо, що зараз у мене є фрагмент даних рядка XML, і я хочу перетворити його в об'єкт Item.java. Дані XML (перелік коду 3) виглядають так

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:item ns1:id="2" xmlns:ns1="http://blogs.sun.com/teera/ns/item">
<ns1:itemName>Bar</ns1:itemName>
<ns1:price>80</ns1:price>
</ns1:item>

Потім я можу зняти цей xml-код до об'єкта Item

...
ByteArrayInputStream xmlContentBytes = new ByteArrayInputStream (xmlContent.getBytes());
JAXBContext context = JAXBContext.newInstance(Item.getClass());
Unmarshaller unmarshaller = context.createUnmarshaller();
//note: setting schema to null will turn validator off
unmarshaller.setSchema(null);
Object xmlObject = Item.getClass().cast(unmarshaller.unmarshal(xmlContentBytes));
return xmlObject;
...

Повний перелік кодів див. У списку кодів 2 (main.java). Джерело XML може надходити у багатьох формах як з потоку, так і з файлу. Єдина відмінність - знову ж таки, параметр методу:

...
unmarshaller.unmarshal(new File("Item.xml")); // reading from file
...
// inputStream is an instance of java.io.InputStream, reading from stream
unmarshaller.unmarshal(inputStream);

Перевірка за допомогою XML-схеми

Останнє, що я хочу тут зазначити, - це перевірка вхідного XML зі схемою перед видаленням об'єкта Java. Я створюю файл XML-схеми під назвою item.xsd. Повний перелік кодів див. У списку кодів 4 (Item.xsd). Тепер мені потрібно зареєструвати цю схему для перевірки.

...
Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File("Item.xsd"));
unmarshaller.setSchema(schema); //register item.xsd shcema for validation
...

Коли я намагаюся знімати дані XML до POJO, якщо вхідний XML не відповідає схемі, буде вилучено виняток. Для повного переліку коду, будь ласка, див. Лістинг коду 5 (invalid_item.xml).

javax.xml.bind.UnmarshalException
- with linked exception:
javax.xml.bind.JAXBException caught: null
[org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'item1' is
                                not a valid value for 'integer'.]

Тут я змінюю атрибут 'id' на рядок замість цілого.

Якщо введення XML є дійсним для схеми, дані XML будуть успішно скасовані для об'єкта Item.java.


1
Це виглядає дуже перспективно, і набагато простіше і приємніше працювати з тим, що мені це потрібно, ніж щось велике і складне, як JAXB. На жаль, я не бачу жодного способу перетворення своїх існуючих .XSD у .class файли, з чого насправді потрібно почати. Чи є спосіб це зробити?
Кіт Палмер-молодший

7
На жаль, що блог з навчальним посібником JAXB офлайн.
Луїс С.

ми можемо це зробити легко, використовуючи jaxb2-maven-плагін, перевірте цей підручник journaldev.com/1312/…
Панкай

що складного в ""% java_home% \ bin \ xjc "-p [ваш простір імен] [xsd_file] .xsd"?
gorefest

30

Використання IDE Eclipse: -

  1. скопіюйте xsd у новий / існуючий проект.
  2. Переконайтеся, що у вас на класі є JAR, необхідні JAXB. Завантажити його можна тут .
  3. Клацніть правою кнопкою миші на файл XSD -> Створення -> класи JAXB.

17

найпростіший спосіб - використання командного рядка. Просто введіть у каталог вашого .xsd файлу:

xjc myFile.xsd.

Отже, java породжує всі Pojos.


14

Maven можна використовувати за призначенням, потрібно додати деякі залежності і просто очистити свою програму. Ви отримаєте всі класи, створені автоматично у вашій цільовій папці.

Просто скопіюйте їх з цільового місця в потрібне місце, ось ось пом.xml, який я використав для створення классифікованих файлів xsd:

    <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>jaxb2-maven-plugin</artifactId>

     <executions>
      <execution>
       <goals>
        <goal>xjc</goal>
       </goals>
      </execution>
     </executions>
     <configuration>
      <schemaDirectory>src/main/webapp/schemas/</schemaDirectory>
     </configuration>
    </plugin>

   </plugins>
  </pluginManagement>
 </build>
</project>

Просто розмістіть свої файли xsd під "src / main / webapp / schemas /", і maven знайде їх під час компіляції.

Сподіваюся, це допоможе вам, більше інформації можна знайти на веб- сайті http://www.beingjavaguys.com/2013/04/create-spring-web-services-using-maven.html

Сподіваюся, це допоможе :)


1
Це насправді працює з каталогом ресурсів? (src / main / ресурси / схеми), тому що я продовжую отримувати це:No XSD files found. Please check your plugin configuration.
zygimantus


7

Ну найкращий варіант %java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

У мене також є питання, чи є у нас тут можливість зробити зворотну інженерію. якщо так, чи можемо ми створити xsd з класу pojo?


xjc доступний лише в java6
sree

7

Якщо ви не заперечуєте проти використання зовнішньої бібліотеки, я раніше це використовував Castor .


Якщо ви створюєте код за допомогою Castor, чи все-таки ті згенеровані класи все ще залежать від Caster після факту? Або я міг би перенести ці класи на машину без бібліотек Castor, і вони все ще працюватимуть?
Кіт Палмер-молодший

Ні, створені класи не залежать від бібліотек Castor.
Дейв

Чи є хороші підручники щодо використання Castor для цього? Це виглядає дуже перспективно ... але найменше, Java - це не моя найсильніша мова. Я не впевнений, які файли / пакети Castor мені потрібно завантажити та як насправді зробити генерацію коду ... будь-які покрокові приклади новачка навколо?
Кіт Палмер-молодший

Перегляньте на цій сторінці документацію щодо використання класу Castor SourceGenerator: castor.org/sourcegen.html
Marc

2
Здається, що касторка давно померла ... Посилання на документи - усі 404.
Павло Веселов,

5

Обмеження JAXB.

Я працював над JAXB, на мій погляд, це гарний спосіб поводження з даними між об'єктами XML та Java. Позитивні сторони - це їх доведеність та краща ефективність та контроль над даними під час виконання. При хорошому використанні вбудованих інструментів або сценаріїв це забирає багато зусиль для кодування.

Я виявив, що частина конфігурації - це не просто завдання, і витратив години на налаштування середовища розробки.

Однак я відмовився від цього рішення через дурне обмеження, з яким зіткнувся. Моє визначення XML-схеми (XSD) має атрибут / елемент з назвою "value", і мені доведеться використовувати XSD таким, яким він є. Це дуже невелике обмеження змусило мій крок прив’язки XJC не вдалося із помилкою "Властивість" Значення ", яка вже використовується."

Це пов'язано з реалізацією JAXB, процес прив'язки намагається створити об'єкти Java з XSD, додавши до кожного класу кілька атрибутів, і один з них є атрибутом значення. Коли він обробив мій XSD, він поскаржився, що вже є властивість з цим іменем.


4

Хіба XJC JAXB не є можливою відповіддю на це? Я намагаюся досягти того самого. Все ще у фазі "спроб". Прийшов через XJC, тому подумав про спільний доступ.



1

Якщо говорити про обмеження JAXB, то рішення, що має однакове ім'я для різних атрибутів, додає вбудовані настройки jaxb до xsd:

+

. . обов'язкові декларації. .

або зовнішні налаштування ...

Додаткову інформацію можна переглянути на веб-сайті: http://jaxb.java.net/tutorial/section_5_3-Overriding-Names.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.