I've already tried some approaches but seems to be something on the way I'm doing it.
I created a simple Java class:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "TRANSACTION")
#XmlAccessorType(XmlAccessType.FIELD)
public class CanonicalPropertyJaxb {
#XmlAttribute
protected String edbt;
public String getEdbt() {
return edbt;
}
public void setEdbt(String edbt) {
this.edbt = edbt;
}
}
And that's the XML I receive. I need this XML to generate the Java object and the Java object to generate this same XML whenever I need. So I started just trying to get the EDBT property from the TRANSACTION tag, but It's always returning null.
<TRANSACTION ETYPE='JDEMCU' EDUS='IPAAS_ADM' EDBT='16919' EDTN='0' EDLN='2.000' EKEY='IPAAS_ADM-16919-0-2.000'> <TABLE_1 NAME='F0006Z1' TYPE='1'> <FORMAT_TABLE_F0006Z1 SEQ="1"> <COLUMN_EDUS>IPAAS_ADM</COLUMN_EDUS> <COLUMN_EDBT>16919</COLUMN_EDBT> <COLUMN_EDTN>0</COLUMN_EDTN> <COLUMN_EDLN>2.000</COLUMN_EDLN> <COLUMN_EDCT></COLUMN_EDCT> <COLUMN_TYTN>JDEMCU</COLUMN_TYTN> <COLUMN_EDFT></COLUMN_EDFT> <COLUMN_EDDT /> <COLUMN_DRIN>2</COLUMN_DRIN> <COLUMN_EDDL>0</COLUMN_EDDL> <COLUMN_EDSP></COLUMN_EDSP> <COLUMN_PNID></COLUMN_PNID> <COLUMN_TNAC>02</COLUMN_TNAC> <COLUMN_MCU>200</COLUMN_MCU> <COLUMN_STYL>CB</COLUMN_STYL> <COLUMN_DC>FINANCEREPORTTESTBSBU</COLUMN_DC> <COLUMN_LDM>3</COLUMN_LDM> <COLUMN_CO>00200</COLUMN_CO> <COLUMN_AN8>0</COLUMN_AN8> <COLUMN_AN8O>0</COLUMN_AN8O> <COLUMN_CNTY></COLUMN_CNTY> <COLUMN_ADDS></COLUMN_ADDS> <COLUMN_FMOD></COLUMN_FMOD> <COLUMN_DL01>Finance Report Test BS BU</COLUMN_DL01> <COLUMN_DL02></COLUMN_DL02> <COLUMN_DL03></COLUMN_DL03> <COLUMN_DL04></COLUMN_DL04> <COLUMN_RP01>DOM</COLUMN_RP01> <COLUMN_RP02>CAN</COLUMN_RP02> <COLUMN_RP03>NAA</COLUMN_RP03> <COLUMN_RP04>NAA</COLUMN_RP04> <COLUMN_RP05>NAA</COLUMN_RP05> <COLUMN_RP06>ZZ</COLUMN_RP06> <COLUMN_RP07>NAA</COLUMN_RP07> <COLUMN_RP08>NAA</COLUMN_RP08> <COLUMN_RP09>NAA</COLUMN_RP09> <COLUMN_RP10>NAA</COLUMN_RP10> <COLUMN_RP11>NAA</COLUMN_RP11> <COLUMN_RP12>NAA</COLUMN_RP12> <COLUMN_RP13>NAA</COLUMN_RP13> <COLUMN_RP14>NAA</COLUMN_RP14> <COLUMN_RP15>NAA</COLUMN_RP15> <COLUMN_RP16>NAA</COLUMN_RP16> <COLUMN_RP17>NAA</COLUMN_RP17> <COLUMN_RP18>NAA</COLUMN_RP18> <COLUMN_RP19>NAA</COLUMN_RP19> <COLUMN_RP20>NAA</COLUMN_RP20> <COLUMN_RP21>NAA</COLUMN_RP21> <COLUMN_RP22>NAA</COLUMN_RP22> <COLUMN_RP23>NAA</COLUMN_RP23> <COLUMN_RP24></COLUMN_RP24> <COLUMN_RP25></COLUMN_RP25> <COLUMN_RP26></COLUMN_RP26> <COLUMN_RP27></COLUMN_RP27> <COLUMN_RP28></COLUMN_RP28> <COLUMN_RP29></COLUMN_RP29> <COLUMN_RP30></COLUMN_RP30> <COLUMN_TA></COLUMN_TA> <COLUMN_TXJS>0</COLUMN_TXJS> <COLUMN_TXA1></COLUMN_TXA1> <COLUMN_EXR1></COLUMN_EXR1> <COLUMN_TC01></COLUMN_TC01> <COLUMN_TC02></COLUMN_TC02> <COLUMN_TC03></COLUMN_TC03> <COLUMN_TC04></COLUMN_TC04> <COLUMN_TC05></COLUMN_TC05> <COLUMN_TC06></COLUMN_TC06> <COLUMN_TC07></COLUMN_TC07> <COLUMN_TC08></COLUMN_TC08> <COLUMN_TC09></COLUMN_TC09> <COLUMN_TC10></COLUMN_TC10> <COLUMN_ND01></COLUMN_ND01> <COLUMN_ND02></COLUMN_ND02> <COLUMN_ND03></COLUMN_ND03> <COLUMN_ND04></COLUMN_ND04> <COLUMN_ND05></COLUMN_ND05> <COLUMN_ND06></COLUMN_ND06> <COLUMN_ND07></COLUMN_ND07> <COLUMN_ND08></COLUMN_ND08> <COLUMN_ND09></COLUMN_ND09> <COLUMN_ND10></COLUMN_ND10> <COLUMN_CC01>N</COLUMN_CC01> <COLUMN_CC02>N</COLUMN_CC02> <COLUMN_CC03>N</COLUMN_CC03> <COLUMN_CC04>N</COLUMN_CC04> <COLUMN_CC05>N</COLUMN_CC05> <COLUMN_CC06>N</COLUMN_CC06> <COLUMN_CC07>N</COLUMN_CC07> <COLUMN_CC08>N</COLUMN_CC08> <COLUMN_CC09>N</COLUMN_CC09> <COLUMN_CC10>N</COLUMN_CC10> <COLUMN_PECC></COLUMN_PECC> <COLUMN_ALS>6</COLUMN_ALS> <COLUMN_ISS>T</COLUMN_ISS> <COLUMN_GLBA></COLUMN_GLBA> <COLUMN_ALCL>00</COLUMN_ALCL> <COLUMN_LMTH></COLUMN_LMTH> <COLUMN_LF>1.0000</COLUMN_LF> <COLUMN_OBJ1></COLUMN_OBJ1> <COLUMN_OBJ2></COLUMN_OBJ2> <COLUMN_OBJ3></COLUMN_OBJ3> <COLUMN_SUB1></COLUMN_SUB1> <COLUMN_TOU>.00</COLUMN_TOU> <COLUMN_SBLI></COLUMN_SBLI> <COLUMN_ANPA>0</COLUMN_ANPA> <COLUMN_CT>FF</COLUMN_CT> <COLUMN_CERT>N</COLUMN_CERT> <COLUMN_MCUS></COLUMN_MCUS> <COLUMN_BTYP></COLUMN_BTYP> <COLUMN_PC>.00</COLUMN_PC> <COLUMN_PCA>.00</COLUMN_PCA> <COLUMN_PCC>.00</COLUMN_PCC> <COLUMN_INTA></COLUMN_INTA> <COLUMN_INTL></COLUMN_INTL> <COLUMN_D1J /> <COLUMN_D2J /> <COLUMN_D3J /> <COLUMN_D4J /> <COLUMN_D5J /> <COLUMN_D6J /> <COLUMN_FPDJ /> <COLUMN_CAC>.00</COLUMN_CAC> <COLUMN_PAC>.00</COLUMN_PAC> <COLUMN_EEO>N</COLUMN_EEO> <COLUMN_ERC></COLUMN_ERC> <COLUMN_USER>IPAAS_ADM</COLUMN_USER> <COLUMN_PID>ER0006Z1E</COLUMN_PID> <COLUMN_UPMJ>2016/12/15</COLUMN_UPMJ> <COLUMN_JOBN>DJDELOG02</COLUMN_JOBN> <COLUMN_UPMT>144810</COLUMN_UPMT> <COLUMN_URCD></COLUMN_URCD> <COLUMN_URAT>.00</COLUMN_URAT> <COLUMN_URDT /> <COLUMN_URAB>0</COLUMN_URAB> <COLUMN_URRF></COLUMN_URRF> <COLUMN_TORG></COLUMN_TORG> <COLUMN_RP31></COLUMN_RP31> <COLUMN_RP32></COLUMN_RP32> <COLUMN_RP33></COLUMN_RP33> <COLUMN_RP34></COLUMN_RP34> <COLUMN_RP35></COLUMN_RP35> <COLUMN_RP36></COLUMN_RP36> <COLUMN_RP37></COLUMN_RP37> <COLUMN_RP38></COLUMN_RP38> <COLUMN_RP39></COLUMN_RP39> <COLUMN_RP40></COLUMN_RP40> <COLUMN_RP41></COLUMN_RP41> <COLUMN_RP42></COLUMN_RP42> <COLUMN_RP43></COLUMN_RP43> <COLUMN_RP44></COLUMN_RP44> <COLUMN_RP45></COLUMN_RP45> <COLUMN_RP46></COLUMN_RP46> <COLUMN_RP47></COLUMN_RP47> <COLUMN_RP48></COLUMN_RP48> <COLUMN_RP49></COLUMN_RP49> <COLUMN_RP50></COLUMN_RP50> <COLUMN_AN8GCA1>0</COLUMN_AN8GCA1> <COLUMN_AN8GCA2>0</COLUMN_AN8GCA2> <COLUMN_AN8GCA3>0</COLUMN_AN8GCA3> <COLUMN_AN8GCA4>0</COLUMN_AN8GCA4> <COLUMN_AN8GCA5>0</COLUMN_AN8GCA5> </FORMAT_TABLE_F0006Z1> </TABLE_1> </TRANSACTION>
What's the right way to get this information?
JAXB is case sensitive. So either change the field to EDBT, or add the uppercase name to #XmlAttribute(name="EDBT").
Related
Got this error
java.lang.IllegalArgumentException: Unsupported element: net
from this example xml file
<?xml version="1.0" encoding="UTF-8"?>
<net>
<node label="A">
...
</node>
<node label="B">
...
</node>
<node label="C">
...
</node>
</net>
with these java code lines
...
FileInputStream file = new FileInputStream("example.xml");
XMLDecoder decoder = new XMLDecoder(file);
Object decodedResistors = (Object) decoder.readObject();
file.close();
...
Do not use java.beans.XMLDecoder for deserialisation custom XML payloads. It was not designed for that. Read article Long Term Persistence of JavaBeans Components: XML Schema. It contains some example XML payloads which can be deserialised back by XMLDecoder:
<?xml version="1.0" encoding="UTF-8" ?>
<java version="1.4.0" class="java.beans.XMLDecoder">
<void id="myController" property="owner"/>
<object class="javax.swing.JButton">
<void method="addActionListener">
<object class="java.beans.EventHandler" method="create">
<class>java.awt.event.ActionListener</class>
<object idref="myController"/>
<string>doIt</string>
</object>
</void>
</object>
</java>
If you need to deserialise custom XML use JAXB or Jackson XML. You need to create a POJO model with JAXB annotations:
#XmlRootElement(name = "net")
#XmlAccessorType(XmlAccessType.FIELD)
class Net {
#XmlElement(name = "node")
private List<Node> nodes;
// getters, setters, toString
}
#XmlAccessorType(XmlAccessType.FIELD)
class Node {
#XmlAttribute
private String label;
// getters, setters, toString
}
Example usage:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.util.List;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
JAXBContext jaxbContext = JAXBContext.newInstance(Net.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object net = unmarshaller.unmarshal(xmlFile);
System.out.println(net);
}
}
prints:
Net{nodes=[Node{label='A'}, Node{label='B'}, Node{label='C'}]}
See also:
java.lang.IllegalArgumentException: Unsupported element: rss
Here is a test case using a file from SCORM for imsmanifest,xml. This XML has been in use for about 5 or more years, and being a standard I don't want to change it unless required to get this to work.
You can find the xsd file here
The error occurs between <organizations default="CYBER4.ORG"> and <organization identifier="CYBER4.ORG">
In my project, this is the entry from my pom.xml for my jaxb version
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
to generate the Java code I ran (this is the install of xjc for Ubuntu 14.04)
$ xjc -version
xjc 2.2.4-2
$ xjc -verbose -p org.cyber4.scorm2004.xml.manifest.imscp imscp_v1p2.xsd
The output generates (amongst other things)
public class OrganizationsType {
#XmlAttribute(name = "default")
#XmlIDREF
#XmlSchemaType(name = "IDREF")
protected Object _default;
}
and
public class OrganizationType {
#XmlAttribute(name = "identifier", required = true)
#XmlJavaTypeAdapter(CollapsedStringAdapter.class)
#XmlID
#XmlSchemaType(name = "ID")
protected String identifier;
}
This is the test code
package org.cyber4.scorm2004.build;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.cyber4.scorm2004.xml.manifest.imscp.ManifestMetadataType;
import org.cyber4.scorm2004.xml.manifest.imscp.ManifestType;
import org.cyber4.scorm2004.xml.manifest.imscp.ObjectFactory;
import org.cyber4.scorm2004.xml.manifest.imscp.OrganizationType;
import org.cyber4.scorm2004.xml.manifest.imscp.OrganizationsType;
import org.cyber4.scorm2004.xml.manifest.imscp.ResourcesType;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
public class TestSCORMBuilder {
public static void main(String args[]) {
try {
ObjectFactory objectFactory = new ObjectFactory();
/*
* <metadata />
*/
ManifestMetadataType metadataType = objectFactory.createManifestMetadataType();
/*
* <organizations default="CYBER4.ORG">
* <organization identifier="CYBER4.ORG" />
* </organizations>
*/
// https://java.net/jira/browse/JAXB-872
OrganizationsType organizationsType = objectFactory.createOrganizationsType();
organizationsType.setDefault("CYBER4.ORG");
OrganizationType organizationType = objectFactory.createOrganizationType();
organizationType.setIdentifier("CYBER4.ORG");
organizationsType.getOrganization().add(organizationType);
/*
* <resources />
*/
ResourcesType resourcesType = objectFactory.createResourcesType();
/*
* <manifest>
* <metadata/ >
* <organizations default="CYBER4.ORG">
* <organization identifier="CYBER4.ORG" />
* </organizations>
* <resources />
* <manifest>
*/
ManifestType manifestType = objectFactory.createManifestType();
manifestType.setMetadata(metadataType);
manifestType.setOrganizations(organizationsType);
manifestType.setResources(resourcesType);
JAXBContext context = JAXBContext.newInstance("org.cyber4.scorm2004.xml.manifest.imscp");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,
"http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd");
marshaller.marshal(objectFactory.createManifest(manifestType), System.out);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
When I run the code I get this error
javax.xml.bind.MarshalException
- with linked exception:
[com.sun.istack.internal.SAXException2: Object "CYBER4.ORG" is found in an IDREF property but this object doesnt have an ID.]
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:95)
at org.cyber4.scorm2004.build.TestSCORMBuilder.main(TestSCORMBuilder.java:73)
Caused by: com.sun.istack.internal.SAXException2: Object "CYBER4.ORG" is found in an IDREF property but this object doesnt have an ID.
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:237)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.errorMissingId(XMLSerializer.java:1045)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$IDREFTransducedAccessorImpl.print(TransducedAccessor.java:275)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$IDREFTransducedAccessorImpl.print(TransducedAccessor.java:254)
at com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty.serializeAttributes(AttributeProperty.java:86)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeAttributes(ClassBeanInfoImpl.java:360)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:678)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:343)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:685)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:143)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:145)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:115)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:317)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:324)
at com.sun.xml.internal.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:60)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:483)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
... 3 more
If I comment out line 37
organizationsType.setDefault("CYBER4.ORG");
it generates this XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manifest xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd">
<metadata/>
<organizations>
<organization identifier="CYBER4.ORG"/>
</organizations>
<resources/>
</manifest>
but it's missing the
default="CYBER4.ORG"
in <organizations> which is required for imsmanifest.xml to be valid.
This looks like this bug but I want to be sure I haven't missed anything.
default should not contain the id of the object you want to reference, but an object with the same id than the object you want to reference.
Try to replace :
organizationsType.setDefault("CYBER4.ORG");
with :
OrganizationType o = new OrganizationType()
o.setIdentifier("CYBER4.ORG");
organizationsType.setDefault(o);
If organizationType has already been set you can maybe also try :
organizationsType.setDefault(organizationType);
I'm trying to unmarshall the following XML with JAXB:
<artist xmlns="http://www.spotify.com/ns/music/1">
<name>Basement Jaxx</name>
<albums>
<album href="spotify:album:3xOulZzGRe4Ycwm59iCdKg">
<name>Back 2 the Wild</name>
<artist href="spotify:artist:4YrKBkKSVeqDamzBPWVnSJ">
<name>Basement Jaxx</name>
</artist>
<released>2013</released>
<id type="upc">5055489272702</id>
<album>
</albums>
</artist>
When I use #XmlTransient on the artist within the album to just skip it, it gets parsed regardless.
What can I do to make JAXB handle fields marked #XmlTransient correctly?
Edit 1 - files
Test xml:
<artist>
<name>Adema</name>
<albums>
<album href="spotify:album:07tjJowJIddz8c74x5WOvj">
<name>Topple the Giants</name>
<artist href="spotify:artist:3n4ersmDo55xV4fPSCKpXb">
<name>Adema</name>
</artist>
<released>2013</released>
<id type="upc">886443922082</id>
<availability>
<territories>AD AT AU BE CA CH DE DK EE ES FI FR GB HK IE IS IT LI LT LU LV MC MX MY NL NO NZ PL PT SE SG US</territories>
</availability>
</album>
<album href="spotify:album:06QaJLqG068uXHQbAcPZKU">
<name>Kill The Headlights</name>
<artist href="spotify:artist:3n4ersmDo55xV4fPSCKpXb">
<name>Adema</name>
</artist>
<released>2007</released>
<id type="upc">4030816195283</id>
<availability>
<territories>AD AT BE CH DE DK EE ES FI FR GB IE IS IT LI LT LU LV MC NL NO PL PT SE</territories>
</availability>
</album>
</albums>
</artist>
XTest.java:
package dao.spotify;
import dao.spotify.lookup.entities.LookupArtist;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.helpers.DefaultValidationEventHandler;
public class XTest {
public XTest() {
load();
}
public void load() {
try {
File file = new File("c:/tmp/test5.xml");
JAXBContext jc = JAXBContext.newInstance(LookupArtist.class);
Unmarshaller um = jc.createUnmarshaller();
um.setEventHandler(new DefaultValidationEventHandler());
LookupArtist spotifyArtistWrapper = (LookupArtist) um.unmarshal(file);
System.err.println("Done");
} catch (JAXBException ex) {
ex.printStackTrace();
}
}
public static void main(String... args) {
XTest test = new XTest();
}
}
LookupArtist.java:
package dao.spotify.lookup.entities;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "artist")
#XmlAccessorType(XmlAccessType.FIELD)
public class LookupArtist {
#XmlElement
private String name;
#XmlElementWrapper(name = "albums")
#XmlElement(name = "album")
private List<LookupInnerAlbum> albums = new ArrayList();
}
LookupInnerAlbum.java:
package dao.spotify.lookup.entities;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#XmlRootElement(name = "album")
#XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerAlbum {
#XmlAttribute
private String href;
private String name;
private int released;
private String id;
private LookupInnerAvailability availability;
#XmlTransient
private LookupInnerArtist artist;
}
LookupInnerAvailability.java:
package dao.spotify.lookup.entities;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "availability")
#XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerAvailability {
#XmlElement
private String territories;
}
LookupInnerArtist.java:
package dao.spotify.lookup.entities;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(name = "artist")
#XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerArtist {
#XmlElement
private String name;
#XmlAttribute
private String href;
}
When running this I get:
DefaultValidationEventHandler: [ERROR]: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
Location: line 6 of file:/c:/tmp/test5.xml
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:120)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:105)
at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:262)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:498)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:480)
at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:150)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2717)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:229)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:136)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:141)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:150)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:168)
at dao.spotify.XTest.load(XTest.java:30)
at dao.spotify.XTest.<init>(XTest.java:21)
at dao.spotify.XTest.main(XTest.java:38)
When I run your example I get the same thing. The error message is correct unexpected element (uri:"", local:"artist") the element exists in the XML but you have not mapped to it. The expected elements you have mapped to are <{}id>,<{}released>,<{}name>,<{}availability> the element <{}artist> does not appear there because you have excluded it with #XmlTransient.
DefaultValidationEventHandler: [ERROR]: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
Location: line 6 of file:/Users/bdoughan/GIT/EclipseLink-Trunk3/Scratch/src/dao/spotify/test5.xml
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)
Note about DefaultValidationEventHandler. This class represents the default validation event rules for JAXB 1.0 which are different from JAXB 2.0. The following is from the Javadoc (see: http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/helpers/DefaultValidationEventHandler.html)
JAXB 1.0 only default validation event handler. This is the default
handler for all objects created from a JAXBContext that is managing
schema-derived code generated by a JAXB 1.0 binding compiler.
This handler causes the unmarshal and validate operations to fail on
the first error or fatal error.
This handler is not the default handler for JAXB mapped classes
following JAXB 2.0 or later versions. Default validation event
handling has changed and is specified in Unmarshaller and Marshaller.
If you had not specified this as the ValidationEventHandler then your document would have unmarshalled correctly.
UPDATE
I'm afraid I don't understand; I thought that I had mapped artist when
specifying: private LookupInnerArtist artist;? When changing the
DefaultValidationEventHandler to ValidationEventCollector (correct?)
everything works fine, even if I have specified artist as
#XmlTransient.
Since you have specified #XmlAccessorType(XmlAccessType.FIELD) all fields except those annotated with #XmlTransient will be considered mapped.
I can still see artist when debugging, though it has a null value.
Even though artist is annotated with #XmlTransient it still remains available on your class. Since it is now considered unmapped it will not be populated by the unmarshal operation.
For More Information
http://blog.bdoughan.com/2012/04/jaxb-and-unmapped-properties.html
I am having trouble customizing my JAXB Marshaller. I have my marshaller code:
public void marshaller(AddressMap addMap, File file) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(AddressMap.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(addMap, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
The output looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ObjectMap>
<Prop> Indiana</Prop>
<Prop1>39.0</Prop1>
<Prop2>-85.0</Prop2>
<Prop3> United States</Prop3>
<Prop4> Hueseman Rd</Prop4>
<Prop5> 8540-8704</Prop5>
<Prop6> 47001</Prop6>
</ObjectMap>
Instead, I need it to look like this:
<bean class="classname">
<property name="PropName" value="object value" />
<property name="PropName1" value="object value" />
<property name="PropName2" value="object value" />
<property name="PropName3" value="object value" />
<property name="PropName4" value="object value" />
<property name="PropName5" value="object value" />
<property name="PropName6" value="object value" />
</bean>
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You could use MOXy's #XmlDesciminatorNode and #XmlPath extensions to map this use case. Below is an example based on what I assume your object model looks like.
ObjectMap
The #XmlDescriminatorNode annotation allows you to specify that you want a specific XML attribute to serve as the inheritance indicator.
package forum13884782;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
#XmlRootElement(name="bean")
#XmlDiscriminatorNode("#class")
public class ObjectMap {
}
AddressMap
The #XmlDescriminatorValue annotation is used to specify the value on the descriminator node that relates to the instance class. In this class we also use the #XmlPath annotation to indicate which property element we wish to map to based on the value of its name attribute.
package forum13884782;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
#XmlRootElement(name="bean")
#XmlAccessorType(XmlAccessType.FIELD)
#XmlDiscriminatorValue("AddressMap")
public class AddressMap extends ObjectMap {
#XmlPath("property[#name='PropName']/#value")
String prop;
#XmlPath("property[#name='PropName1']/#value")
String prop1;
#XmlPath("property[#name='PropName2']/#value")
String prop2;
#XmlPath("property[#name='PropName3']/#value")
String prop3;
#XmlPath("property[#name='PropName4']/#value")
String prop4;
#XmlPath("property[#name='PropName5']/#value")
String prop5;
#XmlPath("property[#name='PropName6']/#value")
String prop6;
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
The following demo code will convert the XML message to an instance of AddressMap and then back to XML.
package forum13884782;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(AddressMap.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum13884782/input.xml");
AddressMap addressMap = (AddressMap) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(addressMap, System.out);
}
}
input.xml/Output
<bean class="AddressMap">
<property name="PropName" value="Indiana" />
<property name="PropName1" value="39.0" />
<property name="PropName2" value="-85.0" />
<property name="PropName3" value="United States" />
<property name="PropName4" value="Hueseman Rd" />
<property name="PropName5" value="8540-8704" />
<property name="PropName6" value="47001" />
</bean>
For More Information
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-moxy-extension.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
I'm looking for something to easily create an Object to access a large XML file.
The XML file looks like this:
<?xml version="1.0" encoding="WINDOWS-1252"?>
<vzg:vzg erstellt_von="##" erstellt_am="###" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:vzg="###" xsi:schemaLocation="###">
<auswahl sicht="B" basisfplp_id="0" basisve_id="0">
<fplp vzg_id="0" periode="2012/2013"/>
<version vzg_id="###" name="###"/>
<strecke name="11801">
<von baukms_nr="###" km="#.#"/>
<bis baukms_nr="###" km="#.#"/>
</strecke>
<bst vzg_id="#" name="#" kurzbez="##" bez="####" kritart="#"/>
<bst vzg_id="#" name="#" kurzbez="##" bez="####" kritart="#"/>
<bst vzg_id="#" name="#" kurzbez="##" bez="####" kritart="#"/>
<bst vzg_id="#" name="#" kurzbez="##" bez="####" kritart="#"/>
<bst vzg_id="#" name="#" kurzbez="##" bez="####" kritart="#"/>
...
I want an Object to calculate with some of the XML Attributes.
Like:
List vzg_id=vzg.auswahl.bst;
int res=vzg_id.get(3) * vzg.auswahl.strecke.von.baukms_nr;
Since the XML has about 16000 Lines it's difficult to create a class for every XMLElement.
What I've done now:
MainClass
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import javax.xml.bind.JAXB;
public class Main
{
public static void main(String[] args)
{
VZG vzg = JAXB.unmarshal(new File("./XMLVZG.xml"), VZG.class);
System.out.println(vzg.erstellt_am+ " "+vzg.erstellt_von+"\n"+vzg.aw.sicht);
}
}
Class VZG
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class VZG
{
#XmlElement(name="auswahl")
AuswahlSicht aw;
#XmlAttribute(name="erstellt_von")
String erstellt_von;
#XmlAttribute(name="erstellt_am")
String erstellt_am;
#XmlAttribute(name="xsi")
String xmlns_xsi;
}
Class Auswahl
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="auswahl")
public class AuswahlSicht
{
#XmlAttribute(name="basisfplp_id")
int basisfplp_id;
#XmlAttribute(name="basisve_id")
int basisve_id;
#XmlAttribute(name="sicht")
String sicht;
}
So I'm now able to get the Attributes of the Root and the Cild, but I have still about 1000 childs with Attributes left and I'm looking for an automated way to parse the XML to get an object.
Simple Description:
XML File
<root>
<child>
<Subchild id="1"/>
<subsubchild id=2/>
<subsubchild id=33/>
</child>
</root>
The object should then be like this:
List subsubchilds = root.child.subchild.subsubchild;
int id_one=subsubchilds.get(0);
Thanks in advance
It is rarely a good idea to write JAXB classes by hand for existing XML. JDK has special command line tool to generate these classes for you (xjc) from XML schema. If schema is not available you could try to generate schema from XML (various tools can do that - for example XMLSpy) and then generate classes using xjc.