1

i have situation where i have 2 structurally different XML's , i need to extract data from these (at a time only XML needs to be parsed) and submit it to some logic and then fill to a common format.

<xml1>
    <a>hello</a>
    <b>shreyas</b>
    <c>123</c>
</xml1>

and

<xml2>
    <d>
        <name>
            <my>hello</my>
        </name>
    </d>
    <e>shreyas</e>
    <f>124</f>
</xml2>

and common object to fill

public class Gobj {

    String fName;
    String lName;
    String id;
}

i was looking to some kind of run time annotations resolver. I tried with JaxbIntros implemented by Jboss on top of Jaxb , but i could not find xpath support for it.

Also this problem can be solved using basic SAX parser, but i wanted some method like jaxb etc.,. where readability of the code can be easy.

-Thanks Shreyas

1 Answer 1

1

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

Below is how you could support this use case using MOXy's external mapping file extension.

Metadata for XML 1

We will use the standard JAXB annotations to map the Gobj class to the first XML representation.

package forum17652921;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="xml1")
@XmlAccessorType(XmlAccessType.FIELD)
public class Gobj {

    @XmlElement(name="a")
    String fName;

    @XmlElement(name="b")
    String lName;

    @XmlElement(name="c")
    String id;

}

Metadata for XML 2

We will use MOXy's external mapping document to map the same class to the second XML representation. By default the mapping document is used to augment the metadata supplied by annotations. If we set xml-metadata-complete flag to true then you can completely replace that metadata.

<?xml version="1.0"?>
<xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="forum17652921"
    xml-accessor-type="FIELD"
    xml-mapping-metadata-complete="true">
    <java-types>
        <java-type name="Gobj">
            <xml-root-element name="xml2"/>
            <java-attributes>
                <xml-element java-attribute="fName" xml-path="d/name/my/text()"/>
                <xml-element java-attribute="lName" name="e"/>
                <xml-element java-attribute="id" name="f"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

Demo

In the demo code below there are two instances of JAXBContext. We will use the first to read XML representation 1 to an instance of Gobj. Then we will use the second JAXBContext to marshal the same instance of Gobj to the second XML representation.

package forum17652921;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc1 = JAXBContext.newInstance(Gobj.class);

        Unmarshaller unmarshaller = jc1.createUnmarshaller();
        File xml = new File("src/forum17652921/xml1.xml");
        Gobj gobj = (Gobj) unmarshaller.unmarshal(xml);

        Map<String, Object> properties = new HashMap<String, Object>(1);
        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "forum17652921/oxm.xml");
        JAXBContext jc2 = JAXBContext.newInstance(new Class[] {Gobj.class}, properties);

        Marshaller marshaller = jc2.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(gobj, System.out);
    }

}

xml1.xml

<xml1>
    <a>hello</a>
    <b>shreyas</b>
    <c>123</c>
</xml1>

Output

<?xml version="1.0" encoding="UTF-8"?>
<xml2>
   <d>
      <name>
         <my>hello</my>
      </name>
   </d>
   <e>shreyas</e>
   <f>123</f>
</xml2>

For More Information

Sign up to request clarification or add additional context in comments.

3 Comments

THanks a lot Blaise, i tried the same in my environment but i'm getting "javax.xml.bind.JAXBException: property "eclipselink.oxm.metadata-source" is not supported" expection.
i created jaxb.properties and placed it along my model classes , i guess it is not getting picked up. i still get the same not supported excepition.
Sorry for so many comments it worked finally :) Thanks Blaise,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.