Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are a couple of different ways to support this use case.</p> <hr> <p><strong>OPTION #1 - DOM Approach</strong></p> <p>You could always use a DOM parser to convert the XML to a <code>Document</code> perform an XPath against it to get the value of the <code>id</code> element and then unmarshal the document based on the result</p> <hr> <p><strong>OPTION #2 - SAX Approach</strong> </p> <p><em><strong>LookAheadUnmarshallerHandler</em></strong></p> <p>You could leverage a SAX parser and JAXB's <code>UnmarshallerHandler</code> mechanism and do the following:</p> <ul> <li>Create a <code>ContentHandler</code> that queues up SAX events until the necessary information is discovered.</li> <li>Create/retrieve a <code>JAXBContext</code> based on the value of the <code>id</code> element.</li> <li>Create an <code>UnmarshallerHandler</code> from the <code>JAXBContext</code>.</li> <li>Call the queued events on the <code>UnmarshallerHandler</code>.</li> <li>Set the <code>UnmarshallerHandler</code> on the <code>XMLReader</code> as the <code>ContentHandler</code>.</li> <li>Retrieve the unmarshalled object from the <code>UnmarshallerHandler</code>.</li> </ul> <pre class="lang-java prettyprint-override"><code>package forum13397834; import java.util.*; import javax.xml.bind.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; public class LookAheadUnmarshallerHandler extends DefaultHandler { private XMLReader xmlReader; private List&lt;Event&gt; events = new ArrayList&lt;Event&gt;(); private UnmarshallerHandler unmarshallerHandler; public LookAheadUnmarshallerHandler(XMLReader xmlReader) { this.xmlReader = xmlReader; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { events.add(new StartElement(uri, localName, qName, attributes)); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if("id".equals(localName) || "id".equals(qName)) { Characters characters = (Characters) events.get(events.size() - 1); String value = characters.getString(); JAXBContext jc; try { if("1234".equals(value)) { jc = JAXBContext.newInstance(Root1.class); } else if("5678".equals(value)) { jc = JAXBContext.newInstance(Root2.class); } else { jc = JAXBContext.newInstance(Root3.class); } unmarshallerHandler = jc.createUnmarshaller().getUnmarshallerHandler(); } catch(JAXBException e) { throw new RuntimeException(e); } unmarshallerHandler.startDocument(); for(Event event : events) { event.event(unmarshallerHandler); } unmarshallerHandler.endElement(uri, localName, qName); xmlReader.setContentHandler(unmarshallerHandler); } else { events.add(new EndElement(uri, localName, qName)); } } @Override public void characters(char[] ch, int start, int length) throws SAXException { events.add(new Characters(ch, start, length)); } public Object getResult() throws JAXBException { return unmarshallerHandler.getResult(); } private static abstract class Event { public abstract void event(ContentHandler contentHandler) throws SAXException; } private static class StartElement extends Event { private String uri; private String localName; private String qName; private Attributes attributes; public StartElement(String uri, String localName, String qName, Attributes attributes) { this.uri = uri; this.localName = localName; this.qName = qName; this.attributes = attributes; } @Override public void event(ContentHandler contentHandler) throws SAXException { contentHandler.startElement(uri, localName, qName, attributes); } } private static class Characters extends Event { private char[] ch; private int start; private int length; public Characters(char[] ch, int start, int length) { this.ch = ch; this.start = start; this.length = length; } @Override public void event(ContentHandler contentHandler) throws SAXException { contentHandler.characters(ch, start, length); } public String getString() { return new String(ch, start, length); } } private static class EndElement extends Event { private String uri; private String localName; private String qName; public EndElement(String uri, String localName, String qName) { this.uri = uri; this.localName = localName; this.qName = qName; } @Override public void event(ContentHandler contentHandler) throws SAXException { contentHandler.endElement(uri, localName, qName); } } } </code></pre> <p><strong>JAVA MODEL</strong></p> <p>The following object model is based on the classes you mention in your question.</p> <p><em><strong>UserA</em></strong></p> <pre class="lang-java prettyprint-override"><code>package forum13397834; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="root") public class UserA { } </code></pre> <p><em><strong>UserB</em></strong></p> <pre class="lang-java prettyprint-override"><code>package forum13397834; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="root") public class UserB { } </code></pre> <p><em><strong>UserC</em></strong></p> <pre class="lang-java prettyprint-override"><code>package forum13397834; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="root") public class UserC { } </code></pre> <p><strong>INPUT (input.xml)</strong></p> <p>We will use the XML document from your question as the input for this example.</p> <pre><code>&lt;root&gt; &lt;user&gt; &lt;id&gt;1234&lt;/id&gt; &lt;/user&gt; &lt;XMLelements&gt; ... &lt;/XMLelements&gt; &lt;/root&gt; </code></pre> <p><strong>DEMO CODE</strong></p> <pre class="lang-java prettyprint-override"><code>package forum13397834; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.*; public class Demo { public static void main(String[] args) throws Exception { SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); XMLReader xmlReader = spf.newSAXParser().getXMLReader(); LookAheadUnmarshallerHandler handler = new LookAheadUnmarshallerHandler(xmlReader); xmlReader.setContentHandler(handler); xmlReader.parse(new InputSource("src/forum13397834/input.xml")); Object object = handler.getResult(); System.out.println(object.getClass()); } } </code></pre> <p><strong>Output</strong></p> <pre><code>class forum13397834.UserA </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload