I would like to use JAXB to read and write only a few parts of a very large XML. I would like to be able to do this without having to define a root object class for every element and attribute in the XML. The example below outlines what I need:
I have the XML
<A>
<B/>
<C/>
<D/>
</A>
I would like to use JAXB to get two functions
public String getC() {
...
return C
}
public void writeC(String C) {
... // replaces C value with the paramter C inside the XML
}
Without having to define a new class A with the annotations for B, C, and D.
How can I do this with JAXB? Is there a faster / more efficient way to achieve what I am trying to do than JAXB or a simple File Reader and Writer?
The purpose of this is to use a GUI to load and edit config settings that are stored in an XML file. Thank you.
I managed to solve this by using StAX instead. It offered complete flexibility for me to pick out which tags and which attrbitues I needed.
There is a project called EclipseLink MOXy that could solve this type of problem using JAXB. It allows you to map an existing java bean to or from xml and define exceptions from default JAXB using xml or json for the mapping description.
Related
I am using a Web service and it returns a String value. But in my output, that value is in XML format:
String point = request.getParameter("point");
try {
String latLonListCityNames = proxy.latLonListCityNames(new BigInteger(point));
request.setAttribute("point", latLonListCityNames);
System.out.println(latLonListCityNames);
} catch (RemoteException e) {
e.printStackTrace();
}
I expect the output to be for example "Oklahoma", but the actual output is:
<?xml version='1.0' ?>
<dwml version='1.0' xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">
<latLonList>
<cityNameList>
Oklahoma
</cityNameList>
</dwml>
The responses of web-services are commonly (not always) in XML. If you need to extract the data from xml string response to your desired format, say, Java Objects (POJO), you need a converter i.e. marshaling and Un-marshaling of data.
Simple solution
Use JAXB.
What is JAXB? From wiki
Java Architecture for XML Binding (JAXB) is a software framework that allows Java developers to map Java classes to XML representations. JAXB provides two main features: the ability to marshal Java objects into XML and the inverse, i.e. to unmarshal XML back into Java objects.
How does it fit into my use-case?
Create a simple POJO for the type of response you are expecting. And then use JAXB convertor to convert them for you.
Eg. If you are expecting a list of cityName in response, you can create your POJO like below..
CityModel.java
public Class CityModel {
private List<String> cityName;
// if more field required, add here.
}
Sample XML response should be..
<ListOfCities>
<CityName>My City</CityName>
<CityName>Your City</CityName>
<CityName>So Pity</CityName>
</ListOfCities>
Then, pass this xml response string to JAXB binding for Equivalent Class type. i.e. CityModel.
How to do all this? Can You Share some good example?
Read this tutorial to get started.
I have problem with the response type names, they are not well described, how can I map them with different name that I want?
You might need to look at links below, they key part is investigate more about #XmlRootElement, #XmlAttribute, #XmlElement, etc annotations for custom configurations.
Few more important links that can help later on?
Convert Soap XML response to Object
convert xml to java object using jaxb (unmarshal)
Using JAXB for XML With Java
JAXB Unmarshalling Example: Converting XML into Object
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.
Given the XML example:
<fooRoot>
<bar>
<lol>LOLOLOLOL</lol>
</bar>
<noob>
<boon>
<thisIsIt></thisIsIt>
</boon>
</noob>
</fooRoot>
Which should be mapped to:
class MyFoo {
String lol;
String thisIsIt;
Object somethingUnrelated;
}
Constraints:
XML should not be transformed, it is provided as a parsed org.w3c.dom.Document object.
Class does not and will not map 1:1 to the XML.
I'm only interested to map specific paths of the XML to specific fields of the object.
My dream solution would look like:
#XmlMapped
class MyFoo {
#XmlElement("/fooRoot/bar/lol")
String lol;
#XmlElement("/noob/boon/thisIsIt")
String thisIsIt;
#XmlIgnore
Object somethingUnrelated;
}
Does anything likewise exists? What I've found either required a strict 1:1 mapping (e.g. JMX, JAXB) or manual iteration over all fields (e.g. SAX, Commons Digester.)
JiBX binding definitions come the nearest to what I'm lokking for. However, this tool is ment to marshall/unmarshall complete hierarchy of Java objects. I only would like to extract parts of an XML document into an existing Java bean at runtime.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You can do this with MOXy:
#XmlRootElement(name="fooRoot")
class MyFoo {
#XmlPath("bar/lol/text()")
String lol;
#XmlElement("noob/boon/thisIsIt/text()")
String thisIsIt;
#XmlTransient
Object somethingUnrelated;
}
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
Try XStream. It's super easy. Hope it helps! I don't have time now for a full example :)
One option could be write a custom annotation which will take the XPath expression as input and do the bindings.
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.
I am using XStream to serialize Java objects to XML. Is it possible to customize XStream so that when it serializes an object it inserts an attribute in the root XML element?
Let's say I have
class A{
int foo = 1;
}
I want XStream to serialize instances of A to look like:
<A type="text/xml">
<foo>1</foo>
</A>
Where the attribute text/xml is automatically added to the root element.
My use case is serializing my java object and insert it as the content element inside Atom entry documents. The end result would look like:
<feed>
<content type="text/xml">
<foo>1</foo>
</content>
</feed>
I do not require being able to unmarshall the feed. I need a generic solution that is agnostic to the class of the object I am serializing.
Can I achieve this with XStream?
The only way are the the XStream.useAttributeFor(...) methods.
This would force you to configure XStream for each object type you are using though, thus not agnostic.
So I don't think XStream is the tool you need.