Tạo các lớp Java từ các tệp .XSD?


127

Tôi có một tệp lược đồ .XSD SDK QuickBooks khổng lồ xác định các yêu cầu / phản hồi XML mà tôi có thể gửi / nhận từ QuickBooks.

Tôi muốn có thể dễ dàng tạo các lớp Java từ các tệp .XSD này, sau đó tôi có thể sử dụng để sắp xếp các đối tượng XML thành các đối tượng Java và các đối tượng Java thành XML.

Có cách nào làm dễ hơn không...?

Lý tưởng nhất, nó sẽ không yêu cầu bất kỳ thư viện nào bên ngoài bản phân phối Java cơ bản vào thời gian chạy. Nhưng tôi linh hoạt ...


6
Nếu bạn muốn tạo thủ công, hãy đặt tệp .xsd trong dự án nhật thực của bạn, nhấp chuột phải vào tệp, sau đó nhấn "tạo"
Junchen Liu

Câu trả lời:


121

JAXB thực hiện chính xác những gì bạn muốn. Nó được tích hợp vào JRE / JDK bắt đầu từ 1.6


7
Thật không may, chức năng này sẽ không còn khả dụng kể từ Java 9. Điều này là do các lớp liên quan (đặc biệt là các lớp com.sun.tools.xjc. *) Sẽ không còn có sẵn thông qua JDK.
Marco

4
Tôi không nghĩ việc loại bỏ điều này khỏi JDK sẽ là một vấn đề, bởi vì dự án java.net (được liên kết trong câu trả lời) có thể sẽ ở lại.
stmoebius

1
Như được giải thích ở đây , bạn có thể thêm các phụ thuộc trong Java 9 bằng một đối số dòng lệnh hoặc thêm phụ thuộc theo cách thủ công.
Matthias Rrid

118

Để mở rộng các nhận xét "sử dụng JAXB" ở trên,

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

ví dụ, "%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Đợi một chút và nếu bạn có tệp XSD được định dạng tốt, bạn sẽ nhận được một số lớp Java được định dạng tốt


3
Cảm ơn rất nhiều! Để tạo các lớp cấp cao nhất thay vì đóng gói, hãy xem: stackoverflow.com/questions/13175224/ . Và nếu nó dẫn đến xung đột tên lớp, hãy xem: stackoverflow.com/questions/13414407/
vào

38

Nếu bạn muốn bắt đầu mã hóa Java thành XML và XML sang Java trong chưa đầy 5 phút, hãy thử Tuần tự hóa XML đơn giản. Đừng dành hàng giờ để học API JAXB http://simple.sourceforge.net/doad/stream/doc/tutorial/tutorial.php

Tuy nhiên, nếu bạn thực sự quan tâm đến việc học JAXB, thì đây là một hướng dẫn tuyệt vời http://bloss.oracle.com/teera/entry/jaxb_for_simple_java_xml

Nội dung hướng dẫn:

JAXB để tuần tự hóa Java-XML đơn giản

Có một số cách để thực hiện tuần tự hóa XML trong Java. Nếu bạn muốn kiểm soát chi tiết về phân tích cú pháp và tuần tự hóa, bạn có thể sử dụng SAX, DOM hoặc Stax để có hiệu suất tốt hơn. Tuy nhiên, điều tôi thường muốn làm là ánh xạ đơn giản giữa POJO và XML. Tuy nhiên, việc tạo các lớp Java để thực hiện phân tích cú pháp sự kiện bằng tay không phải là chuyện nhỏ. Gần đây tôi đã tìm thấy JAXB là một ánh xạ hoặc tuần tự hóa Java-XML nhanh chóng và thuận tiện.

JAXB chứa rất nhiều tính năng hữu ích, bạn có thể kiểm tra việc triển khai tham khảo tại đây. Blog của Kohsuke cũng là một tài nguyên tốt để tìm hiểu thêm về JAXB. Đối với mục blog này, tôi sẽ chỉ cho bạn cách thực hiện tuần tự hóa Java-XML đơn giản với JAXB.

POJO sang XML

Giả sử tôi có một đối tượng Java Item. Tôi muốn tuần tự hóa một đối tượng Item thành định dạng XML. Điều tôi phải làm trước tiên là chú thích POJO này với một vài chú thích XML từ gói javax.xml.bind.annotation. *. Xem danh sách mã 1 cho Item.java

Từ mã

  • @XmlRootElement(name="Item") chỉ ra rằng tôi muốn là thành phần gốc.
  • @XmlType(propOrder = {"name", "price"}) chỉ ra thứ tự mà tôi muốn phần tử được sắp xếp trong đầu ra XML.
  • @XmlAttribute(name="id", ...) chỉ ra rằng id là một thuộc tính cho phần tử gốc.
  • @XmlElement(....) chỉ ra rằng tôi muốn giá và tên là thành phần trong Mục.

Tôi Item.javađã sẵn sàng. Sau đó tôi có thể tiếp tục và tạo tập lệnh JAXB cho mục sắp xếp thứ tự.

//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"));

Để biết mã hoàn chỉnh, vui lòng xem Mã Liệt kê 2 main.java. Tệp Mã đầu ra 3 item.xmlđược tạo. Nó trông như thế này:

<?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>

Dễ dàng phải không? Bạn có thể thay thế kênh XML đầu ra dưới dạng chuỗi văn bản, Luồng, Trình ghi, ContentHandler, v.v. bằng cách đơn giản thay đổi tham số của phương thức marshal (...) như

...
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 sang POJO

Hãy đảo ngược quá trình. Giả sử rằng bây giờ tôi có một phần dữ liệu chuỗi XML và tôi muốn biến nó thành đối tượng Item.java. Dữ liệu XML (Mã liệt kê 3) trông giống như

<?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>

Sau đó tôi có thể sắp xếp mã xml này thành đối tượng Item bằng cách

...
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;
...

Để biết mã hoàn chỉnh, vui lòng xem Mã Liệt kê 2 (main.java). Nguồn XML có thể có nhiều dạng từ cả Stream và file. Sự khác biệt duy nhất, một lần nữa, là tham số phương thức:

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

Xác thực với Lược đồ XML

Điều cuối cùng tôi muốn đề cập ở đây là xác thực XML đầu vào bằng lược đồ trước khi sắp xếp lại đối tượng Java. Tôi tạo một tệp lược đồ XML có tên là item.xsd. Để biết mã hoàn chỉnh, vui lòng xem Mã Liệt kê 4 (Item.xsd). Bây giờ những gì tôi phải làm là đăng ký lược đồ này để xác nhận.

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

Khi tôi cố gắng sắp xếp dữ liệu XML thành POJO, nếu XML đầu vào không tuân theo lược đồ, ngoại lệ sẽ bị bắt. Để biết mã hoàn chỉnh, vui lòng xem Mã liệt kê 5 (không hợp lệ).

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'.]

Ở đây tôi thay đổi thuộc tính 'id' thành chuỗi thay vì số nguyên.

Nếu đầu vào XML hợp lệ với lược đồ, dữ liệu XML sẽ được sắp xếp thành công đối tượng Item.java.


1
Điều này có vẻ rất hứa hẹn, và đơn giản hơn và đẹp hơn để làm việc với những gì tôi cần nó hơn là một thứ gì đó lớn và phức tạp như JAXB. Thật không may, tôi không thấy bất kỳ cách nào để chuyển đổi các tệp .XSD hiện có của mình sang các tệp. Class, đây thực sự là những gì tôi cần để bắt đầu. Có cách nào để làm việc này không?
Keith Palmer Jr.

7
Không may là blog có Hướng dẫn JAXB đang ngoại tuyến.
Luis C.

chúng ta có thể làm điều đó một cách dễ dàng bằng cách sử dụng jaxb2-maven-plugin, kiểm tra hướng dẫn này journaldev.com/1312/ mẹo
Pankaj

có gì phức tạp về ""% java_home% \ bin \ xjc "-p [không gian tên của bạn] [xsd_file] .xsd"?
gorefest

30

Sử dụng IDE Eclipse: -

  1. sao chép xsd vào một dự án mới / hiện có.
  2. Hãy chắc chắn rằng bạn có JARB yêu cầu JAR trong đường dẫn lớp của bạn. Bạn có thể tải xuống ở đây .
  3. Nhấp chuột phải vào tệp XSD -> Tạo -> các lớp JAXB.

17

cách dễ nhất là sử dụng dòng lệnh. Chỉ cần gõ vào thư mục của tệp .xsd của bạn:

xjc myFile.xsd.

Vì vậy, java sẽ tạo ra tất cả Pojos.


14

Maven có thể được sử dụng cho mục đích này, bạn cần thêm một số phụ thuộc và chỉ cần làm sạch ứng dụng của bạn. Bạn sẽ nhận được tất cả các lớp được tạo tự động trong thư mục đích của bạn.

Chỉ cần sao chép chúng từ mục tiêu đến vị trí mong muốn, đây là pom.xml mà tôi đã sử dụng để tạo phân loại từ các tệp 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>

Chỉ cần đặt các tệp xsd của bạn trong "src / main / webapp / schemas /" và maven sẽ tìm thấy chúng tại thời gian biên dịch.

Hy vọng điều này sẽ giúp bạn, có thể tìm thêm thông tin tại http://www.beingjavaguys.com/2013/04/create-spring-web-service-USE-maven.html

Hy vọng nó sẽ giúp :)


1
Điều này thực sự làm việc với thư mục tài nguyên? (src / main / resource / No XSD files found. Please check your plugin configuration.
schitions


7

Vâng lựa chọn tốt nhất là %java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

Tôi cũng có một câu hỏi nếu chúng ta có một lựa chọn để làm kỹ thuật đảo ngược ở đây. nếu có, chúng ta có thể tạo xsd từ lớp pojo không?


xjc chỉ khả dụng trong java6
sree

7

Nếu bạn không phiền khi sử dụng thư viện bên ngoài, tôi đã sử dụng Castor để làm điều này trong quá khứ.


Nếu bạn tạo mã bằng Castor, thì những lớp được tạo đó có còn phụ thuộc vào Caster không? Hoặc tôi có thể di chuyển các lớp đó sang một máy không có thư viện Castor và chúng vẫn hoạt động không?
Keith Palmer Jr.

Không, các lớp được tạo không phụ thuộc vào các thư viện Castor.
dave

Có hướng dẫn tốt nào về cách sử dụng Castor để làm việc này không? Có vẻ rất hứa hẹn ... nhưng Java, nói, ít nhất, không phải là ngôn ngữ mạnh nhất của tôi. Tôi không chắc chắn những tập tin / gói Castor nào tôi cần tải xuống và làm thế nào để thực sự tạo mã ... bất kỳ ví dụ newbie từng bước nào xung quanh?
Keith Palmer Jr.

Kiểm tra trang này để biết tài liệu về cách sử dụng lớp Castor SourceGenerator: castor.org/sourcegen.html
Marc

2
Có vẻ như thầu dầu đã chết từ lâu ... Các liên kết của Docs đều là 404.
Pawel Veselov

5

Giới hạn JAXB.

Tôi đã làm việc trên JAXB, theo ý kiến ​​của tôi, đó là một cách xử lý dữ liệu tốt giữa các đối tượng XML và Java. Các mặt tích cực được chứng minh và tốt hơn về hiệu suất và kiểm soát dữ liệu trong thời gian chạy. Với việc sử dụng tốt các công cụ hoặc tập lệnh được xây dựng, nó sẽ lấy đi rất nhiều nỗ lực mã hóa.

Tôi thấy phần cấu hình không phải là một nhiệm vụ ngay lập tức và đã dành hàng giờ để thiết lập môi trường phát triển.

Tuy nhiên tôi đã bỏ giải pháp này do một giới hạn ngớ ngẩn mà tôi phải đối mặt. Định nghĩa lược đồ XML (XSD) của tôi có một thuộc tính / thành phần có tên "value" và tôi phải sử dụng XSD như hiện tại. Ràng buộc rất nhỏ này đã buộc bước XJC ràng buộc của tôi không thành công với Lỗi "Thuộc tính 'Giá trị' đã được sử dụng."

Điều này là do triển khai JAXB, quá trình liên kết cố gắng tạo các đối tượng Java từ XSD bằng cách thêm một vài thuộc tính cho mỗi lớp và một trong số chúng là thuộc tính giá trị. Khi nó xử lý XSD của tôi, nó đã phàn nàn rằng đã có một thuộc tính có tên đó.


4

Không phải XJC của JAXB là câu trả lời khả dĩ cho vấn đề này sao? Tôi đang cố gắng để đạt được điều tương tự. Vẫn đang trong giai đoạn "cố gắng". Đã qua XJC, vì vậy nghĩ đến việc chia sẻ.


2

JAXB nổi tiếng

Có một plugin maven có thể làm điều này cho bạn ở bất kỳ giai đoạn xây dựng nào bạn muốn.

Bạn có thể thực hiện công cụ này theo cả hai cách: xsd <-> Java


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.