Java unmarshlling XML to Object which are dynamic

2019-02-18 13:41发布

问题:

I'm looking for best tool/way to create and load JAVA objects from XML definitions. I had checked out JAXB, seems pretty nice, but didn't find is there a way to work with Entities which properties are dynamic, or changed from time to time, so want to have something like automatic way of working with entities, without converting Object into predefine Entity object. Does something like that exists?

Workflow would be like this read from XML create class for each Entity with dynamic set of attributes and/or create ORM mapping part for those entities and then all manipulation retrieve/store into db or probably will going to use some NoSQL solution like MongoDB.

回答1:

Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB 2 (JSR-222) expert group.


Check out the following EclipseLink example. It demonstrates how to use dynamic properties with both the JPA and JAXB implementations:

  • http://wiki.eclipse.org/EclipseLink/Examples/MySports

Option #1 - Static Objects with Dynamic Properties

MOXy has an @XmlVirtualAccessMethods extension which allows you to map entries in a map to XML. This allows you to add properties to a static class. In the example below the Customer class has a "real" name property and may have many "virtual" properties.

package blog.metadatasource.refresh;

import java.util.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;

@XmlRootElement
@XmlType(propOrder={"firstName", "lastName", "address"})
@XmlVirtualAccessMethods
public class Customer {

    private String name;
    private Map<String, Object> extensions = new HashMap<String, Object>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object get(String key) {
        return extensions.get(key);
    }

    public void set(String key, Object value) {
        extensions.put(key, value);
    }

}

The virtual properties are defined via MOXy's XML metadata. In the example below we will add two properties: middleName and shippingAddress.

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="blog.metadatasource.refresh">
    <java-types>
        <java-type name="Customer">
            <java-attributes>
                <xml-element
                    java-attribute="middleName"
                    name="middle-name"
                    type="java.lang.String"/>
                <xml-element
                    java-attribute="shippingAddress"
                    name="shipping-address"
                    type="blog.metadatasource.multiple.Address"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

For More Information

  • http://blog.bdoughan.com/2011/06/extensible-models-with-eclipselink-jaxb.html
  • http://blog.bdoughan.com/2011/06/moxy-extensible-models-multi-tenant.html
  • http://blog.bdoughan.com/2011/06/moxy-extensible-models-multiple.html
  • http://blog.bdoughan.com/2011/06/moxy-extensible-models-refresh-example.html

Option #2 - Dynamic Objects

MOXy also offers full dynamic object models:

DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, null, null, null);

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(inputStream);

DynamicEntity address = jaxbContext.newDynamicEntity("org.example.Address");
address.set(street, "123 A Street");
address.set(city, "Any Town");
customer.set("address", address);

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(customer, System.out);

For More Information

  • http://wiki.eclipse.org/EclipseLink/UserGuide/MOXy
  • http://wiki.eclipse.org/EclipseLink/Examples/MOXy/Dynamic


回答2:

So, you're basically trying to make POJO's (plain old Java objects) using XML files? They are just like data classes, right?

I'm a big fan of XStream, which is really easy to use and works great if you don't need validation. I've used Castor when validation against a schema was required. I just used XStream to save an object to an xml file and then I can read it back in from anywhere, even if I change the data values associated with the object (which I think is what you mean by "dynamic set of attributes", right?).