This is more of an academic question, but I started working on configuring JAXB schema validation because I was researching what would happen using more than one schema with an element name conflict. Is it possible to configure JAXB and have schema files which support an XML document which looks something like this?
<my:inventory
xmlns:my="http://www.my.com"
xmlns:ab="http://www.ab.com"
xmlns:xy="http://www.xy.com">
<my:products>
<ab:product>
<id>123</id>
<desc>some ap product</desc>
<price>12.22</price>
</ab:product>
<xy:product>
<key>123</key>
<title>some xy product</title>
<cost>63.45</cost>
</xy:product>
</my:products>
</my:inventory>
The basic idea is to have product information from both AB company and XY company. The two companies have the same data but store them in different tags. I would like to have MY company schema to define an inventory of products from the two other companies.
I started to create the XSD files and the JAXB annotated classes for this. It quickly spiraled into an unending stream of configuration and parsing exceptions, so I thought I'd ask.
Yes it is possible to have JAXB support XML documents with more than one namespace. You end up with something like the following:
#XmlAccessorType(XmlAccessType.FIELD)
public class Products {
#XmlElement(name="product", namespace="http://www.ab.com")
private Product product1;
#XmlElement(name="product", namespace="http://www.xy.com")
private Product product2;
}
For More Information
I have written more about JAXB and namespaces on my blog:
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Related
i have one question. What is the best way to serialize in java 1 object to few xml with different schema? For example we have this java bean:
class User {
String name;
String gender;
String age;
}
And i want to serialize it to first
<user>
<name>bobby</name>
<gender>male</gender>
<age>40</age>
</user>
second
<info>
<employer>
<data>
<name>bobby</name>
</data>
<meta>
<gender>male</gender>
<age>40</age>
</meta>
</employer>
</info>
and maybe another one xml. What you think?
You could refer to this answer. The JAXB lib generate the serialization xml file based on a .xsd file. And of course you can customize the .xsd file for your own purpose.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Metadata Representation
Generally object-to-XML providers offer different ways of specifying metadata. Annotations is one way of specifying metadata and in all instances of seen annotations correspond to only one representation. So you need to look for a provider that offers an alternate approach such as an XML mapping document or programmatic metadata.
Path Based Mapping
Generally object-to-XML providers offer mapping through a 1-to-1 relationship between objects/properties and levels of nesting. To map to your second representation you need a provider that is able to do path based mapping.
MOXy offers both items that you are looking for. Below is a link to an example where a single object model is mapped to both the Google and Yahoo weather APIs:
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html
I am trying to work out how to unmarshall and XML document to a Java document.
The top of the xml document looks like this
<xs:myData xmlns:xs="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com example.xsd ">
There is a schema file whose top section looks like this:
<schema targetNamespace="http://www.example.com"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.example.com">
I would like to unmarshall the xml document using Spring/JaxB and eventually convert it to a JPA object. I am not sure how to go about so i looked for examples on google and came up with this http://thoughtforge.net/610/marshalling-xml-with-spring-ws-and-jaxb/
I understand most of it except how or where the schema is used.
I have seen other examples where the schema is explicitly specified, i.e.
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
unmarshaller.setSchema(sysConfigSchema);
RootElement root = (RootElement)unmarshaller.unmarshal(
new File("example1.xml"));
How is the schema shown in the first link used to validate the xml document?
Are there any disadvantages to using Spring's jaxb2Marshaller as opposed to direct use of JAXB?
What is the effect of having the namespace next to the XmlElement annotation? (See the Person class)
I would appreciate any more examples showing Spring/REST with unmarshalling with schema validation.
Thanks
As far as I know JAXB does not parse xsi attribute to dereference XSD, load it and use for validation. Perhaps that was done to disable automatic validation, otherwise it would be problematic to switch it off :)
Spring Jaxb2Marshaller was obviously added to implement the same interface org.springframework.oxm.Marshaller (which is implemented also by CastorMarshaller, JibxMarshaller, ...). It is very powerful and allows you to tune JAXBContext in very flexible way (I can't imagine the scenario when provided API is not enough). From pattern point of new Jaxb2Marshaller is a builder, so it does not add anything to core JAXB functionality. But there are some evident advantages. For example, schema loading is very simple. In the article the Spring context refers the person.xsd (<property name="schema" value="classpath:schema/person.xsd"/>) which one need to put into resources explicitly. Then JAXB marshaller/unmarshaller will use this schema to validate XML when XML is generated/loaded.
#XmlElement(..., namepsace="xxx") will automatically generate this XML element with a specified namespace. It's rare case if somebody does not use namespaces. I would say writing XSD without namespaces is not normal, as you want to avoid the element name collision.
Using JAXB with RestTemplate is very simple. You need to be sure that JAXB runtime is in your classpath (JDK 6 already has it) and your bean is annotated with #XmlRootElement. Then just use Person person = restTemplate.getForObject(restServiceUrl, Person.class),
I have an XML content without defined attributes, like this:
<rootElement>
<subElement1/>
</rootElement>
I want to populate this XML content with required attributes defined in XML Schema (XSD) for this XML.
For example, according to XSD subElement1 has required attribute 'id'.
What is the best way (for Java processing) to detect that and add such attributes to XML?
We need to add required attributes and set appropriate values for them.
As a result for example above we need to have the following XML:
<rootElement>
<subElement1 id="some-value"/>
</rootElement>
In the XML schema definition, i.e. XSD file, attributes are optional by default. To make an attribute required, you have to define:
<xs:attribute name="surname" type="xs:string" use="required"/>
You will find a very good introduction on XML and XML Schema Definitions, i.e. XSD, on W3 Schools.
In Java the equivalent of defining a XML schema is using JAXB, i.e. Java API for XML Binding that is included into Java SE. There you would define, e.g.
#XmlRootElement
public class Person { public #XmlAttribute(required=true) String surname; }
Hope this could clarify your question.
I would suggest you to use JAXB for that. Search the Internet for tutorials.
Steps to proceed further with JAXB,
Generate Java files using JAXB by providing the schema
Unmarshal your XML to generated Java classes (beans). Don't do validation or set validation handler here.
Populate those classes with appropriate values. required elements can be found using annotation look up. JAXB annotation for element would look like something, #XmlElement(name = "ElementName", required = true). And an attribute annotation would be something similar to this, #XmlAttribute(required = true)
Marshal your bean back to XML. You can validate your bean using ValidationHandler, while marshalling. Below is the sample code snippet,
marshller = JAXBContext.newInstance(pkgOrClassName).createUnmarshaller();
marshller.setSchema(getSchema(xsd)); // skip this line for unmarshaller
marshller.setEventHandler(new ValidationHandler()); // skip this line for unmarshaller
Use a DOM parser.Has methods to traverse XML trees, access, insert, and delete nodes
I have had the same idea of Cris but I think that with this validator you don't have information about the point in which you have had the error.
I think that you have to create or extend your own validator.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I have an object graph that I would like to convert to and from JSON and XML, for the purposes of creating a REST-style API. It strikes me that someone must have done this already, but a quick search using Google and Stack Overflow reveals nothing.
Does anyone know of a suitable (Apache or equivalent license preferred) library to do this?
GSON from google : http://code.google.com/p/google-gson/,
or
Jackson the library used in spring :https://github.com/FasterXML/jackson
and I would concur with others suggesting jaxb for XML to pojo, well supported lots of tools : its the standard.
For POJO to XML I suggest using JAXB (there are other libraries as well, such as XStream for example, but JAXB is standardized).
For JSON I don't know anything, but if you want to implement a RESTful API, you might be interested in JSR-311 which defines a server-side API for RESTful APIs and Jersey, which is its reference implementation.
Use Xstream http://x-stream.github.io/ for xml and JSON http://www.json.org/java/ for JSON. I dont think there is one library that does both.
Or write a wrapper which delegates to XStream renderers/JSON renderers depending on what you want.
I think you may be looking for something similar to what is here: JSON.org Java section
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) supports mapping a single object model to both XML and JSON with the same metadata:
http://blog.bdoughan.com/2011/08/binding-to-json-xml-geocode-example.html
License Information
http://wiki.eclipse.org/EclipseLink/FAQ/General#How_is_EclipseLink_Licensed.3F
DOMAIN MODEL
Below is the domain model we will use for this example. For this example I'm just using the standard JAXB (JSR-222) annotations which have are available in the JDK/JRE since Java SE 6.
Customer
package forum658936;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
String firstName;
#XmlElement(nillable=true)
String lastName;
#XmlElement(name="phone-number")
List<PhoneNumber> phoneNumbers;
}
PhoneNumber
package forum658936;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
#XmlAttribute
int id;
#XmlValue
String number;
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
XML
input.xml
This is the XML that our demo code will read in and convert to domain objects.
<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<firstName>Jane</firstName>
<lastName xsi:nil="true"/>
<phone-number id="123">555-1234</phone-number>
</customer>
Things to note about the XML:
The xsi:nil attribute is used to indicate that the lastName is null.
The phone-number element is a complex type with simple content (see: http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html).
JSON
Output
Below is the JSON that was output by running the demo code.
{
"firstName" : "Jane",
"lastName" : null,
"phone-number" : [ {
"id" : 123,
"value" : "555-1234"
} ]
}
Things to note about the JSON:
The null value is used to represent that the lastName is null. There is no presence of the xsi:nil attribute.
The collect of phone numbers is of size 1 and is correctly bound by square brackets. Many libraries incorrectly treat collections of size 1 as JSON objects.
The property of type int was correctly marshalled without quotes.
In the XML representation id was an attribute, but in the JSON representation there is not need for it to be specially represented.
DEMO CODE
In the demo code below we will convert an XML document to objects, and then convert those same instances to JSON.
Demo
MOXy doesn't just interpret JAXB annotations it is a JAXB implementation so the standard JAXB runtime APIs are used. JSON binding is enabled by specifying MOXy specify properties on the Marshaller.
package forum658936;
import java.io.File;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum658936/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.marshal(customer, System.out);
}
}
Json-lib is licensed under the Apache 2.0 license.
It can also transform JSON objects to XML, but you'd need to convert your POJOs to JSON through it first.
Personally I would tackle the two separately; and to convert JSON<->XML via JSON<-> Pojo <-> XML.
With that: Java<->POJO with JAXB (http://jaxb.dev.java.net; also bundled with JDK 1.6) with annotations (XStream is ok too); and for JSON, Jackson's ObjectMapper (http://jackson.codehaus.org/Tutorial). Works nicely with Jersey, and I am use it myself (current Jersey version does not bundle full Pojo data binding by default, but will in near future)
I would actually not use any of xml libs to produce "json": XStream and JAXB/Jettison can produce kind of JSON, but it uses ugly conventions that are rather non-intuitive.
EDIT (18-Jul-2011): Jackson actually has an extension called "jackson-xml-databind" that can read/write XML, similar to JAXB. So it can be used for both JSON and XML, to/from POJOs.
Last I saw on the website, XStream will do both. It supports XML and JSON as serialization targets.
There are almost literally hundreds. My favorites are GSON for POJO <-> JSON and castor-xml for POJO <-> XML.
As a bonus both are licensed under Apache License 2.0 style licenses.
Have a look at Genson library http://code.google.com/p/genson/wiki/GettingStarted.
It is easy to use, performant and was designed with extension in mind.
Actually it does json/java conversion but not xml. However xml support may be added in a future version.
I'm using it in web applications and REST web services in jersey, but also in some cases to store objects in their json form into a database.
Ah and it's under Apache 2.0 license.
I'm using Java and XStream to parse a google geocode request over http. My idea is to have an Address class with all the geocode attr's (ie. lat/long, city, provice/state etc) but I'm having problems parsing the xml with xstream.
The google response is similar to this:
<?xml version="1.0" encoding="UTF-8" ?>
<kml xmlns="http://earth.google.com/kml/2.0"><Response>
<name>98 St. Patrick St, Toronto</name>
<Status>
<code>200</code>
<request>geocode</request>
</Status>
<Placemark id="p1">
<address>98 St Patrick St, Toronto, ON, Canada</address>
<AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"> <Country><CountryNameCode>CA</CountryNameCode><CountryName>Canada</CountryName><AdministrativeArea><AdministrativeAreaName>ON</AdministrativeAreaName><Locality><LocalityName>Toronto</LocalityName><Thoroughfare><ThoroughfareName>98 St Patrick St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>M5T</PostalCodeNumber></PostalCode></Locality></AdministrativeArea></Country></AddressDetails>
<ExtendedData>
<LatLonBox north="43.6560378" south="43.6497426" east="-79.3864912" west="-79.3927864" />
</ExtendedData>
<Point><coordinates>-79.3896388,43.6528902,0</coordinates></Point>
</Placemark>
</Response></kml>
That doesn't show up very well, but the meat of the code is in the AddressDetails tag.
Anyway, I'm new to Java and XStream so the API terminology is a bit confusing for me. I just need to be able to write some mapper that maps all these tags (ie. CountryName) to an attribute within my Address object, (ie. address.country = blah) The address object will be pretty simple, mainly just strings for country name etc and floats for lat/long.
The docs and example just show straight mapping where each xml tag maps directly to the attribute of the same name of the object. In my case however, the tags are named different than the object attr's. A quick point in the right direction is all I'm looking for really.
I've used XStream in several projects. Unfortunately, your problem isn't really what XStream is designed to solve. You might be able to use its converter mechanism to achieve your immediate goal, but you'll run into limitations. In a nutshell, XStream isn't designed to do conversion of Tree Structure A into Tree Structure B -- it's purpose is to convert from a Java domain model into some reasonable XML. XStream is a great tool when you don't care much about the details of the XML produced. If you care more about the XML than the Java objects, look at XMLBeans -- the Java is ugly, but it's incredibly schema-compliant.
For your project, I'd run the Google XML schema through XML beans, generate some Java that will give you a more literate way of hand-coding a converter. You could use a raw DOM tree, but you'd have code like myAddress.setStreet(root.getFirstChild().getAttribute("addr1"))). With XML beans, you say things like myAddress.setStreet(googleResult.getAddress().getStreetName();
I'd ignore JAXB as it's attempt to separate interface from implementation adds needless complexity. Castor might be a good tool to consider as well, but I haven't used it in years.
In a nutshell, there aren't a lot of good Object-to-Object or XML-to-Object converters that handle structure conversion well. Of those I've seen that attempt declarative solutions, all of them seemed much more complicated (and no more maintainable) than using XStream/XmlBeans along with hand-coded structure conversions.
Would it be possible to define a separate class specifically for dealing with XStream's mapping? You could then simply populate your AddressDetails object by querying values out of this other object.
I've ended up just using xpath and populating my own address object manually. Seems to work fine.
Have you tried with json format? It should be the same but you'll need to set a com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver as the driver for XStream
You could use EclipseLink JAXB (MOXy) to do this:
package com.example;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name="kml")
public class Address {
private String country;
#XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryName/text()")
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
and
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://earth.google.com/kml/2.0",
xmlns = {
#javax.xml.bind.annotation.XmlNs(
prefix = "ns", namespaceURI ="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.example;
A full example is available here:
http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html