I am connecting to a webservice which has a service deifnition of the following format
<main>
<header>
<data>xyz</data>
</header>
<test>
<![CDATA[<xml><a></a><b></b></xml>]]>
</test>
</main>
How do I use jaxb to create class file for the cdata strcture
First define your schema using the xml-schema format (XSD), and then run the xjc compiler (xsd java compiler) to generate your classes. Once you classes are generated you can create your web service using the #WebService annotation. I posted somes examples on my blog a few monthes ago see: http://plindenbaum.blogspot.com/2006/12/java-16-mustang-jaxb-and.html and http://plindenbaum.blogspot.com/2008/11/web-service-for-onsolubility.html.
hope it helps
JAXB will not be able to parse anything wrapped in a CDATA declaration: the XML parser will always report the string.
If you want to parse this, you need to do the following:
Run JAXB on the original schema, which will specify the content of "test" as a string or "any" (it has to, otherwise it cannot contain a CDATA declaration!)
Run JAXB on the secondary schema, which defines the content of the "test" element.
At runtime, you need to parse the XML document using JAXB, then navigate to the "test" element and parse that element again using JAXB. There won't be another way.
Hope this helps.
Related
I have an application that reads and writes data from/to XML files to/from a DB using JAXB. The "human readability" of these XML files is one of the top priorities in this project as the idea is that XML files from different DBs can be compared to each other.
Now, I have some tables with attributes that hold XML strings themselves which need to be included to my JAXB objects. As I don't have control over these XML strings and readability is key, I helped myself so far with an XmlAdapter that pretty prints the XML from the DB and wraps it in a CDATA element.
The problem of this solution is that the XML string looks a bit lost within the CDATA element and smart text editors with syntax highlighting don't recognize the XML, so they don't highlight the syntax of that XML.
I was wondering therefore if there's a way to "embed" this XML within an element of my JAXB model as if it would be part of the model. So, I need a kind of XmlAdapter that would parse an XML from a String field of my JAXB class and somehow pass the parsing events to the underlying XMLWriter.
I've spent a lot of time looking for a solution combining JAXB and Stax but didn't succeed. In my view I would need some hook exactly between the JAXB and the Stax layer, so that I can customize the events that JAXB sends to the Stax Writers.
Example:
#XmlRootElement
public class MyJaxbModel {
#XmlAttribute
private Integer anAttribute;
#XmlElement
private String xml;
public MyJaxbModel(Integer anAttribute, String xml) {
this.anAttribute = anAttribute;
this.xml = xml;
}
...
}
Then marshalling the following instance of this class
new MyJaxbModel(999, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><element1><child1>bla</child1><child2>ble</child2></element1>");
should result in the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<MyJaxbModel anAttribute="999">
<xml>
<element1>
<child1>bla</child1>
<child2>ble</child2>
</element1>
</xml>
</MyJaxbModel>
Obviously I need it to work also the other way round, i. e. unmarshalling this XML would return me the MyJaxbModel object including the XML string in the xml field.
I have a central xml configuration in an Commons project. This means in this project I don´t know which xml elements in the config exists. I want to hold the root element in the configuration. The requestet configuration item from other project has to be with a class object. This class object contains neccessary information of the requestet xml Element with the jaxb annotation. Is it possible to get a filled object from JAXB with this guidelines?
I have no code examples because I don´t know yet how to start.
JAXB mapps the XML structure into Object oriented graph/hierarchy.
If you don't know the structure/hierarchy of XML, you should use push/pull parsing SAX, StAX, ...
I've got my Java classes derived from XSD with XJC tool. Unmarshaling works fine with default settings. However I've switched to SAX parser implementation (from SAXSource here: http://docs.oracle.com/javase/6/docs/api/index.html?javax/xml/bind/JAXBContext.html) and now unnmarshalling is of course 2 times faster but XML attributes does not get unmarshalled. It means that attribute that is defined as
#XmlAttribute(required=true)
#XmlSchemaType(name = "anySimpleType")
protected String messageId;
is set to null. In XML I have
<Message messageId="123">
...
</Message>
Everything else get unmarshalled properly.
I have this issue with all objects that uses attributes.
I have Apache Xerces implemetation of SAX parser.
It seems that JAXB don't work properly with SAX parser unless parser is set to be namespace aware and correct namespaces are set. DOM parser works fine with namespace aware property set to false.
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.