ChatGPT解决这个技术问题 Extra ChatGPT

Generate Java classes from .XSD files...?

I have a gigantic QuickBooks SDK .XSD schema file which defines XML requests/responses that I can send/receive from QuickBooks.

I'd like to be able to easily generate Java classes from these .XSD files, which I could then use to marshal XML to Java objects, and Java objects to XML.

Is there an easy way to do this...?

Ideally, it would not require any libraries external to the basic Java distro at run-time. But I'm flexible...

If you want manual generation, place the .xsd file in your eclipse project, right click the file, then hit "generate"

E
Ed Norris

To expand on the "use JAXB" comments above,

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

e.g., "%java_home%\bin\xjc" -p com.mycompany.quickbooks.obj quickbooks.xsd

Wait a bit, and if you had a well-formed XSD file, you will get some well-formed Java classes


Great, thanks! To generate top level classes rather than encapsulated see: stackoverflow.com/questions/13175224/…. And if it leads to class name conflicts, see: stackoverflow.com/questions/13414407/…
B
BalusC

JAXB does EXACTLY what you want. It's built into the JRE/JDK starting at 1.6


Unfortunately, this functionality will no longer be available as of Java 9. This is because the classes involved (in particular, the com.sun.tools.xjc.* classes) will no longer be available via the JDK.
I don't think the removal of this from the JDK should be an issue, because the java.net project (linked in the answer) is probably going to stay.
As explained here, you can add the dependencies in Java 9 by a command line argument, or add the dependency manually.
C
Community

If you want to start coding Java to XML and XML to Java in less than 5 minutes, try Simple XML Serialization. Don't spend hours learning the JAXB API http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

However, if you are really keen on learning JAXB, here's an excellent tutorial http://blogs.oracle.com/teera/entry/jaxb_for_simple_java_xml

Contents of tutorial:

JAXB for simple Java-XML serialization

There're a number of way to do XML serialization in Java. If you want fine-grained control over parsing and serialization you can go for SAX, DOM, or Stax for better performance. Yet, what I often want to do is a simple mapping between POJOs and XML. However, creating Java classes to do XML event parsing manually is not trivial. I recently found JAXB to be a quick and convenient Java-XML mapping or serialization.

JAXB contains a lot of useful features, you can check out the reference implementation here. Kohsuke's Blog is also a good resource to learn more about JAXB. For this blog entry, I'll show you how to do a simple Java-XML serialization with JAXB.

POJO to XML

Let's say I have an Item Java object. I want to serialize an Item object to XML format. What I have to do first is to annotate this POJO with a few XML annotation from javax.xml.bind.annotation.* package. See code listing 1 for Item.java

From the code

@XmlRootElement(name="Item") indicates that I want to be the root element.

@XmlType(propOrder = {"name", "price"}) indicates the order that I want the element to be arranged in XML output.

@XmlAttribute(name="id", ...) indicates that id is an attribute to root element.

@XmlElement(....) indicates that I want price and name to be element within Item.

My Item.java is ready. I can then go ahead and create JAXB script for marshaling Item.

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

For complete code Listing please see Code Listing 2 main.java. The output Code Listing 3 item.xml file is created. It looks like this:

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

Easy right? You can alternatively channel the output XML as text String, Stream, Writer, ContentHandler, etc by simply change the parameter of the marshal(...) method like

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

Let's reverse the process. Assume that I now have a piece of XML string data and I want to turn it into Item.java object. XML data (Code listing 3) looks like

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

I can then unmarshal this xml code to Item object by

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

For complete code Listing please see Code Listing 2 (main.java). The XML source can come in many forms both from Stream and file. The only difference, again, is the method parameter:

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

Validation with XML Schema

Last thing I want to mention here is validating input XML with schema before unmarshalling to Java object. I create an XML schema file called item.xsd. For complete code Listing please see Code Listing 4 (Item.xsd). Now what I have to do is register this schema for validation.

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

When I try to unmarshal XML data to POJO, if the input XML is not conformed to the schema, exception will be caught. For complete code Listing please see Code Listing 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'.]

Here I change the 'id' attribute to string instead of integer.

If XML input is valid against the schema, the XML data will be unmarshalled to Item.java object successfully.


This looks very promising, and much simpler and nicer to work with for what I need it for than something big and complicated like JAXB. Unfortunately, I don't see any way to convert my existing .XSD to .class files, which is really what I need to start. Is there a way to do this?
Unfortunatelly the blog with the JAXB Tutorial is offline.
we can do it easily using jaxb2-maven-plugin, check this tutorial journaldev.com/1312/…
what's complicated about ""%java_home%\bin\xjc" -p [your namespace] [xsd_file].xsd"?
K
Kumar Sambhav

Using Eclipse IDE:-

copy the xsd into a new/existing project. Make sure you have JAXB required JARs in you classpath. You can download one here. Right click on the XSD file -> Generate -> JAXB classes.


C
Crozeta

the easiest way is using command line. Just type in directory of your .xsd file:

xjc myFile.xsd.

So, the java will generate all Pojos.


Z
Zoe stands with Ukraine

Maven can be used for the purpose, you need to add some dependencies and just clean your application. You will get all classes created automatically in your target folder.

Just copy them from target to desired place, here is pom.xml that I have used to create classed from xsd files:

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

Just place your xsd files under src/main/webapp/schemas/ and maven will find them at compile time.


Does this actually work with resources directory? (src/main/resources/schemas), because I keep getting this: No XSD files found. Please check your plugin configuration.
C
Community

XMLBeans will do it. Specifically the "scomp" command.

EDIT: XMLBeans has been retired, check this stackoverflow post for more info.


Yeah, but XMLBeans has been discontinued.
XMLBeans is back on track!
C
CoolBeans

Well best option is %java_home%\bin\xjc -p [your namespace] [xsd_file].xsd.

I also have a question if we have an option to do reverse engineering here. if yes can we generate xsd from pojo class?


xjc is available only in java6
K
Keppil

If you don't mind using an external library, I've used Castor to do this in the past.


If you generate code with Castor, are those generated classes still dependent on Caster after the fact? Or could I move those classes to a machine without the Castor libraries, and they'd still work?
No, the generated classes are not dependent on the Castor libraries.
Are there any good tutorials on how to use Castor to do this? It looks very promising... but Java is, to say the least, not my strongest language. I'm not sure what Castor files/packages I need to download and how to actually do the code generation... any step-by-step newbie examples around?
Check out this page for documentation on how to use the Castor SourceGenerator class: castor.org/sourcegen.html
Seems that castor is long dead... Docs links are all 404.
R
RAm

JAXB Limitation.

I worked on JAXB, as per my opinion its a nice way of dealing with data between XML and Java objects. The Positive sides are its proven and better in performance and control over the data during runtime. With a good usage of built tools or scripts it will takes away lot of coding efforts.

I found the configuration part is not a straight away task, and spent hours in getting the development environment setup.

However I dropped this solution due to a silly limitation I faced. My XML Schema Definition ( XSD ) has a attribute/element with name "value" and that I have to use XSD as it is. This very little constraint forced the my binding step XJC failed with a Error "Property 'Value' already used."

This is due to the JAXB implementation, the binding process tries to create Java objects out of XSD by adding few attributes to each class and one of them being a value attribute. When it processed my XSD it complained that there is already a property with that name.


N
Niks

Isn't JAXB's XJC is a possible answer to this? I'm trying to achieve the same thing. Still in the "trying" phase though. Came across XJC, so thought of sharing.


B
BalusC

The well-known JAXB

There is a maven plugin that could do this for you at any build phase you want.

You could do this stuff in both ways: xsd <-> Java


B
BalusC

Talking about JAXB limitation, a solution when having the same name for different attributes is adding inline jaxb customizations to the xsd:

+

. . binding declarations . .

or external customizations...

You can see further informations on : http://jaxb.java.net/tutorial/section_5_3-Overriding-Names.html