I would like to know how to bind an XML tag in a certain namespace to some implementation in Java e.g. the way Mule does with the tags defined in it's various XSD files. Is it related/done with JAXB or is that just for mapping Java beans to XML?
Regards Ola
Check out my article on JAXB and namespaces:
http://bdoughan.blogspot.com/2010/08/jaxb-namespaces.html
With JAXB you can choose the granularity at which namespace information is provided:
At the package level using #XmlSchema
At the type level using #XmlType
At the field/property level using #XmlElement and #XmlAttribute
I dont fully understad your question. Are you asking about unmarshalling ?
If so try use sth like below:
JAXBContext ctx = JAXBContext.newInstance("some.package");
Unmarshaller u = ctx.createUnmarshaller();
XMLInputFactory inFac = XMLInputFactory.newFactory();
XMLStreamReader reader = inFac.createXMLStreamReader(this.getClass().
getResourceAsStream("inputFile.xml"));
JAXBElement<Mule> freestyleElement = u.unmarshal(reader,Mule.class);
Related
I am new about jaxb. My question is the following: using jaxb, is it possible to do automatic mapping from an xml file to a java object?
Starting from xml file, is there something generate the Java class with annotations jaxb relaitve?
It is indeed possible. However, you'll need an XSD rather than an XML file. There are tools out there (Trang, for instance) that can infer an XSD from one or more example XML files.
Take into account that generating this XSD with a tool might get you inaccurate results if the XML sample isn't complete, or if the schema can't be fully represented in a single XML file (exclusive elements, etc).
Once you have an XSD, use xjc in order to generate the marshaller/unmarshaller classes.
xjc myxsd.xsd
This will generate the annotated classes that JAXB will use for marshalling/unmarshalling. Notice you could also have coded these classes yourself. Once you have them, just use them in your code:
File file = new File("myFile.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(MyRootElement.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MyRootElement element = (MyRootElement) jaxbUnmarshaller.unmarshal(file);
Yes, JAXB automatically does marshalling and unmarshalling but it requires a schema file.
JaxB is used to bind XML with Java objects. Using the XSD schema file, it does marshalling and unmarshalling. There are few simple ant tasks like XJC that can be used.
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),
When i create a jaxbcontext with all my classes, jaxb build xml for a class with a namespace from other class.
If i pass to jaxbcontext only one class it work fine.
My classes are generated by xjc.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
})
#XmlRootElement(name = "eReq")
public class EReq {
...
And when i pass only this class to jaxbcontext the output is following.
<eReq><status>UNBLOCKED</status></eReq>
But i put all my classes into jaxb context output will be like this:
<eReq xmlns:ns2="myns1" xmlns:ns3="myns2" xmlns:ns4="http://schemas.xmlsoap.org/soap/envelope/"><status>UNBLOCKED</status></eReq>
This is namespaces from my other classes. Why jaxb put it to this class?
Why jaxb put it to this class?
Because the JAXB context contains the superset of all namespaces that it's created with, and it just puts them all in each document it generates.
It does this because the namespaces need to be added to the root element (to avoid hugely wasteful re-declaration of namespaces on each child element), and it doesn't know in advance which namespaces are required for any given set of bound objects (JAXB supports incremental serialization).
So the JAXB runtime probably could avoid doing that; but it doesn't.
If you don't like it, then you need to build multiple contexts.
When processing a web service response with a quite complex XML structure, I am only interested with a very small subset of information. Lets consider the using JAXB has to be used in this context.
As an example, lets say I am only interested in retrieving d (which can be modeled as a single JAXB bean):
a
b1
c1
c2
b2
d
What is the fastest recommended way to ignore everything else but retrieve d?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
There are a couple of different ways that you could handle this use case:
Option #1 - StreamFilter Any JAXB Implementation
You could use a StAX XMLStreamReader with a StreamFilter to filter out the portions of the XML document that you don't wish to map to:
JAXB filtered parsing
Option #2 - #XmlPath in MOXy JAXB
You could use the #XmlPath extension in MOXy:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class A {
#XmlPath("b2/d/text()")
private String d;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
I think the fastest way would depend on exactly how the xml is formatted. E.g. you could create your own InputStream that wraps the real InputStream and just be on the lookout for "<d>" to trigger you to start passing data through to jaxb.
e.g.
InputStream is = // get real stream
JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
Unmarshaller u = jc.createUnmarshaller();
Object o = u.unmarshal( new MySpecialStream(is) );
If you needed a more xml-like approach then you could create your own XMLStreamReader that only passed on certain calls if you were inside a d element.
e.g.
JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
Unmarshaller u = jc.createUnmarshaller();
XMLStreamReader xsr = XMLInputFactory.newInstance().createXMLStreamReader( ... );
Object o = u.unmarshal( new MyXSRWrapper(xsr) );
Use XPath to select the desired element as a DOM node and unmarshal using that selected node.
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.