JAXB unmarshalling of “generic” real world documents

試著忘記壹切 提交于 2019-12-02 01:29:24

You could do something like the following with JAXB (JSR-222) and StAX (JSR-173):

Demo

A StAX XMLStreamReader can be used to parse the XML document. You can use it to advance to a bar element, then you can read the class attribute and load the appropriate Java class from a ClassLoader. Then you can leverage one of the unmarshal methods that takes a class parameter.

package forum12402215;

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = Bork.class.getClassLoader();
        JAXBContext jc = JAXBContext.newInstance(Bork.class, Gnarf.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();

        StreamSource source = new StreamSource("src/forum12402215/input.xml");
        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(source);
        xsr.nextTag(); // Advance to "foo" element
        xsr.nextTag(); // Advance to "bar" element

        while(xsr.getLocalName().equals("bar")) {
             String className = xsr.getAttributeValue("", "class");
             Class<?> clazz = classLoader.loadClass(className);
             Object object = unmarshaller.unmarshal(xsr, clazz).getValue();
             System.out.println(object);
             xsr.nextTag();
        }
    }

}

Bork

Below is a sample Bork class.

package forum12402215;

public class Bork {

    private String b;

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    @Override
    public String toString() {
        return "Bork(b=" + b + ")";
    }

}

Gnarf

Below is a sample Gnarf class:

package forum12402215;

public class Gnarf {

    private int a;

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "Gnarf(a=" + a + ")";
    }

}

input.xml

Below is he sample document I used used for this example based on the one from your question. I changed the package names.

<?xml version="1.0" encoding="UTF-8"?>
<foo>
    <bar class="forum12402215.Gnarf">
        <a>123</a>
    </bar>
    <bar class="forum12402215.Bork">
        <b>Hello World</b>
    </bar>
</foo>

Output

Below is the output from running the demo code.

Gnarf(a=123)
Bork(b=Hello World)

If the structure really is that simple I'd be tempted to parse the top two levels (foo and the class attribute of bar) myself using an XMLStreamReader, then hand the reader off to the JAXB unmarshaller to parse each bar, assembling the results into a list. I wouldn't bother trying to parse the outer envelope layers using JAXB directly.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!