I am facing an issue when unmarshalling an XML to my XJC Schema based generated classes using JAXB. I have read every post I've found so far, trying already who knows how many things, without success.
I have generated my Java classes using xjc -d "/myDir/src" -p nodeset.generated ./UANodeSet.xsd
, where UANodeSet.xsd is this.
In my Java code, I call unmarshall the NodeSet2.xml file to the generated class UANodeSet
(Root element) like:
String packageName = UANodeSet.class.getPackage().getName();
JAXBContext context = JAXBContext.newInstance(packageName);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setEventHandler(event -> {
System.err.println("JAXB EVENT: " + event.getMessage());
return true; // continue after error
});
String filePath = "C:/Users/mr/Downloads/Opc.Ua.NodeSet2.xml";
File file = new File(filePath);
JAXBElement<UANodeSet> nodeSet = (JAXBElement<UANodeSet>)unmarshaller.unmarshal(new StreamSource(file), UANodeSet.class);
UANodeSet nd = nodeSet.getValue();
This outputs the following:
JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"Models"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"Aliases"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UAObject"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UAObject"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UADataType"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified>
...
and nd
is populated with a UANodeSet
object with null
values.
I confirm I have a file named package-info.java
within the same package (nodeset.generated
) with the following content:
@XmlSchema(
namespace = "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd",
elementFormDefault = XmlNsForm.QUALIFIED)
package nodeset.generated;
import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlSchema;
To have as reference, here is what UANodeSet
looks like:
package nodeset.generated;
import java.util.ArrayList;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElements;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlSchemaType;
import jakarta.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"namespaceUris",
"serverUris",
"models",
"aliases",
"extensions",
"uaObjectOrUAVariableOrUAMethod"
})
@XmlRootElement(name = "UANodeSet")
public class UANodeSet {
@XmlElement(name="NamespaceUris")
protected UriTable namespaceUris;
@XmlElement(name="ServerUris")
protected UriTable serverUris;
@XmlElement(name="Models")
protected ModelTable models;
@XmlElement(name="Aliases")
protected AliasTable aliases;
@XmlElement(name="Extensions")
protected ListOfExtensions extensions;
@XmlElements({
@XmlElement(name="UAObject", type = UAObject.class),
@XmlElement(name="UAVariable", type = UAVariable.class),
@XmlElement(name="UAMethod", type = UAMethod.class),
@XmlElement(name="UAView", type = UAView.class),
@XmlElement(name="UAObjectType", type = UAObjectType.class),
@XmlElement(name="UAVariableType", type = UAVariableType.class),
@XmlElement(name="UADataType", type = UADataType.class),
@XmlElement(name="UAReferenceType", type = UAReferenceType.class)
})
protected List<UANode> uaObjectOrUAVariableOrUAMethod;
@XmlAttribute(name = "LastModified")
@XmlSchemaType(name = "dateTime")
protected XMLGregorianCalendar lastModified;
...
Things I've tried
- Instantiate the
JAXBContext
fromUANodeSet.class
(JAXBContext context = JAXBContext.newInstance(UANodeSet.class);
) => nothing has changed - Add manually
namespace = "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd"
to@XmlType
s and/or@XmlElement
s@XmlRootElement
=>JAXBContext
continues to say the expected elements are<{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified>
- Removing
package-info.java
file completely, and add thenamespace="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd"
attribute everywhere (@XmlType
s,@XmlElement
s,@XmlRootElement
) => no changes.
Basically, I cannot make my JAXBContext
expect the proper namespace for the UANodeSet
elements.
Any help is appreciated, I have been fighting with this since too long already.
Answer
While not a direct answer to your question, I am currently using XJC and JAXB on the exact same schema in this project: https://github.com/digitalpetri/uanodeset
I use jaxb2-maven-plugin
as configured here: https://github.com/digitalpetri/uanodeset/blob/ec3c182f0c808667994951c19f1c7d2b42c46c92/uanodeset-core/pom.xml#L55-L91
Parsing the UANodeSet XML file is simply:
/**
* Read and parse an XML document conforming to the <a
* href="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">UANodeSet</a> schema from an {@link
* InputStream}.
*
* @param inputStream the {@link InputStream} to read from.
* @return a {@link UANodeSet}.
* @throws JAXBException if an error occurs while unmarshalling.
*/
public static UANodeSet parse(InputStream inputStream) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
return (UANodeSet) jaxbContext.createUnmarshaller().unmarshal(inputStream);
}
}
If you can't use my project, maybe you can at least re-use some of the code.