I have a xml as follows:
<VisitorDataList>
<VisitorData>
<Attribute1List>
<Attribute1>
<Attribute1Name>name1</Attribute1Name>
<Attribute1Id>2</Attribute1Id>
</Attribute1>
<Attribute1>
<Attribute1Name>name1</Attribute1Name>
<Attribute1Id>3</Attribute1Id>
</Attribute1>
<Attribute1>
<Attribute1Name>name1</Attribute1Name>
<Attribute1Id>1</Attribute1Id>
</Attribute1>
</Attribute1List>
<Attribute2List>
<Attribute2>
<Attribute2Name>name2</Attribute2Name>
<Attribute2Id>113</Attribute2Id>
</Attribute2>
<Attribute2>
<Attribute2Name>name2</Attribute2Name>
<Attribute2Id>115</Attribute2Id>
</Attribute2>
<Attribute2>
<Attribute2Name>name2</Attribute2Name>
<Attribute2Id>114</Attribute2Id>
</Attribute2>
</Attribute2List>
</VisitorData>
</VisitorDataList>
The Attribute1List and Attribute2List is dynamic for both name and value, so they can be Attribute3List or Attribute4List and so on. Now i want to parse this xml via jAXB, the java bean is like:
#XmlRootElement(name = "VisitorDataList")
public class VisitorDataList {
#XmlElement(name = "VisitorData")
public List<Visitor> getVisitors() {
return visitors;
}
public void setVisitors(List<Visitor> visitors) {
this.visitors = visitors;
}
}
public class Visitor {
private List<String> attributes= new ArrayList<String>();
public List<String> getAttributes() {
return attributes;
}
public void setAttributes(List<String> attributes) {
this.attributes= attributes;
}
}
My question is how to map all the attribute names into one list? Thanks in advance.
You could use JAXB to unmarshal from StAX with a StreamReaderDelegate to strip off the number from the element names. Your JAXB mappings will then be made to elements
Below is a link to an article I wrote where I use this approach to do case insensitive unmarshalling:
http://blog.bdoughan.com/2010/12/case-insensitive-unmarshalling.html
Java Model
VistorDataList
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "VisitorDataList")
public class VisitorDataList {
private List<Visitor> visitors;
#XmlElementWrapper(name="VisitorData")
#XmlElement(name = "AttributeList")
public List<Visitor> getVisitors() {
return visitors;
}
public void setVisitors(List<Visitor> visitors) {
this.visitors = visitors;
}
}
Visitor
import java.util.*;
import javax.xml.bind.annotation.XmlElement;
public class Visitor {
private List<String> attributes = new ArrayList<String>();
#XmlElement(name="AttributeName")
public List<String> getAttributes() {
return attributes;
}
public void setAttributes(List<String> attributes) {
this.attributes = attributes;
}
}
Demo Code
Demo
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
XMLInputFactory xif = XMLInputFactory.newFactory();
StreamSource xml = new StreamSource("src/forum18071557/input.xml");
XMLStreamReader xsr = xif.createXMLStreamReader(xml);
xsr = new StreamReaderDelegate(xsr) {
#Override
public String getLocalName() {
String localName = super.getLocalName();
if(localName.startsWith("Attribute") && localName.endsWith("List")) {
return "AttributeList";
} else if(localName.startsWith("Attribute") && localName.endsWith("Name")) {
return "AttributeName";
} else if(localName.startsWith("Attribute")) {
return "ignore";
} else {
return localName;
}
}
};
xsr = xif.createFilteredReader(xsr, new StreamFilter() {
#Override
public boolean accept(XMLStreamReader reader) {
if(reader.isStartElement() || reader.isEndElement()) {
return !reader.getLocalName().equals("ignore");
} else {
return true;
}
}
});
JAXBContext jc = JAXBContext.newInstance(VisitorDataList.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
VisitorDataList vdl = (VisitorDataList) unmarshaller.unmarshal(xsr);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(vdl, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VisitorDataList>
<VisitorData>
<AttributeList>
<AttributeName>name1</AttributeName>
<AttributeName>name1</AttributeName>
<AttributeName>name1</AttributeName>
</AttributeList>
<AttributeList>
<AttributeName>name2</AttributeName>
<AttributeName>name2</AttributeName>
<AttributeName>name2</AttributeName>
</AttributeList>
</VisitorData>
</VisitorDataList>
I tried your XML file to unmarshal using JAXB but I was only able to parse it statically.You can try it once.
visitor.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VisitorDataList>
<VisitorData>
<AttributeList>
<Attribute>
<AttributeName>name1</AttributeName>
<AttributeId>2</AttributeId>
</Attribute>
<Attribute>
<AttributeName>name1</AttributeName>
<AttributeId>3</AttributeId>
</Attribute>
<Attribute>
<AttributeName>name1</AttributeName>
<AttributeId>1</AttributeId>
</Attribute>
</AttributeList>
<AttributeList>
<Attribute>
<AttributeName>name2</AttributeName>
<AttributeId>113</AttributeId>
</Attribute>
<Attribute>
<AttributeName>name2</AttributeName>
<AttributeId>115</AttributeId>
</Attribute>
<Attribute>
<AttributeName>name2</AttributeName>
<AttributeId>114</AttributeId>
</Attribute>
</AttributeList>
</VisitorData>
visitordatalist.java
package foo.bar.me.too;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="VisitorDataList")
public class visitordatalist {
List<visitordata> vstd;
#XmlElement(name="VisitorData")
public List<visitordata> getVstd() {
return vstd;
}
public void setVstd(List<visitordata> vstd) {
this.vstd = vstd;
}
}
visitordata.java
package foo.bar.me.too;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
public class visitordata {
List<attributelist> atrl;
public String toString() {
return atrl.toString();
}
#XmlElement(name="AttributeList")
public List<attributelist> getAtrl() {
return atrl;
}
public void setAtrl(List<attributelist> atrl) {
this.atrl = atrl;
}
}
attributelist.java
package foo.bar.me.too;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
public class attributelist {
List<attribute> atr;
public String toString() {
return atr.toString();
}
#XmlElement(name="Attribute")
public List<attribute> getAtr() {
return atr;
}
public void setAtr(List<attribute> atr) {
this.atr = atr;
}
}
attribute.java
package foo.bar.me.too;
import javax.xml.bind.annotation.XmlElement;
public class attribute {
String atrName;
String atrId;
public String toString() {
return atrName+" "+atrId;
}
#XmlElement(name="AttributeName")
public String getAtrName() {
return atrName;
}
public void setAtrName(String atrName) {
this.atrName = atrName;
}
#XmlElement(name="AttributeId")
public String getAtrId() {
return atrId;
}
public void setAtrId(String atrId) {
this.atrId = atrId;
}
}
JAXBExample.java
package foo.bar.me.too;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class JAXBExample {
public static void main(String[] args) {
try {
File file = new File("visitor.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(visitordatalist.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
visitordatalist vstdl = (visitordatalist) jaxbUnmarshaller.unmarshal(file);
System.out.println(vstdl.getVstd());
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
There is a special arcane knowledge for some special JAXB implementations. For example, for FasterXML (used in WildFly) you should change one property to make it work (just override an additional method in Delegator):
#Override
public Object getProperty(String name) {
Object property = super.getProperty(name);
if("org.codehaus.stax2.internNames".equals(name)) {
return Boolean.FALSE;
}
return property;
}
Related
I have below XML -
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectWithList>
<MyList>
<abc>hi</abc>
<list>Somewhere</list>
<list>This and that</list>
<list>Something</list>
</MyList>
</objectWithList>
which I want to convert to java object using jaxb unmarshaller.
Java File for xml mapping-
#XmlRootElement
public class ObjectWithList {
#XmlElement
private String abc;
private List<String> list;
#XmlElementWrapper(name="MyList")
#XmlElement
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
}
main driver class code for conversion -
public class Test {
public static void main(String[] args) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(ObjectWithList.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ObjectWithList emps = (ObjectWithList) jaxbUnmarshaller.unmarshal(new File("c:/emp.xml"));
for (String s : emps.getList()) {
System.out.println(s);
}
System.out.println(" ");
}
}
but this is not working. I am getting the below exception -
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; systemId: file:/c:/emp.xml; lineNumber: 1; columnNumber: 10; The processing instruction target matching "[xX][mM][lL]" is not allowed.]
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:563)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:249)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
at com.netspend.idology.Test.main(Test.java:12)
Caused by: org.xml.sax.SAXParseException; systemId: file:/c:/emp.xml; lineNumber: 1; columnNumber: 10; The processing instruction target matching "[xX][mM][lL]" is not allowed.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:177)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
This problem has taken my whole day.
Any kind of help is much appreciated.
Please find below the modified program which works. Also you have to understand about the usage of structure of class and the use of annotation at proper places.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
#XmlRootElement
public class ObjectWithList {
private MyList myList;
#XmlElement(name = "MyList")
public MyList getMyList() {
return myList;
}
public void setMyList(MyList myList) {
this.myList = myList;
}
#Override
public String toString() {
return "ObjectWithList{" + "myList=" + myList + '}';
}
}
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
#XmlRootElement(name = "MyList")
public class MyList {
private String abc;
private List<String> list;
#XmlElement(name = "abc")
public String getAbc() {
return abc;
}
public void setAbc(String abc) {
this.abc = abc;
}
#XmlElement(name = "list")
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
#Override
public String toString() {
return "MyList{" + "abc='" + abc + '\'' + ", list=" + list + '}';
}
}
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.List;
public class Test {
public static void main(String[] args) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(ObjectWithList.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
ObjectWithList emps =
(ObjectWithList)
jaxbUnmarshaller.unmarshal(
new File("D:/someFolder/emp.xml"));
for (String s : emps.getMyList().getList()) {
System.out.println(s);
}
System.out.println(emps);
System.out.println(" ");
}
}
I am trying the above approach that you have mentioned for NodeAdaptar, but I am getting null for my element.
Scenario:
I have to set the value of variable defined in my Java Model(POJO) Class with a value, coming externally(not part of the input XML). This value will be used in some calculation post unmarshal.
input XML: its a huge one. I am able to unmarshall it correctly.
POJO Class:
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 javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement(name="root")
#XmlAccessorType(XmlAccessType.FIELD)
public class MainModelClass {
#XmlPath("abc/def/Result/text()")
#XmlElement(name="Result")
private String result;
#XmlPath("/abc/def/Score/text()")
#XmlElement(name="Score")
private String score;
///This is where I want to populate the external value ///
#XmlElement
#XmlJavaTypeAdapter(PCNDateAdaptar.class)
private PCNDate pcnDateObject;
public PCNDate getPcnDateObject() {
return pcnDateObject;
}
public void setPcnDateObject(PCNDate pcnDateObject) {
this.pcnDateObject = pcnDateObject;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
// Block for overridden toString() //
}
Adaptar Class:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class PCNDateAdaptar extends XmlAdapter<Integer, PCNDate> {
private PCNDate pcnDateObject;
public void setPcnDateObject(PCNDate pcnDateob) {
this.pcnDateObject = pcnDateob;
}
#Override
public PCNDate unmarshal(Integer v) throws Exception {
if(v == null)
return this.pcnDateObject;
else
return this.pcnDateObject;
}
#Override
public Integer marshal(PCNDate v) throws Exception {
if(v == null)
return null;
else
return null;
}
}
PCNDate.class:
public class PCNDate {
private Integer processControlDate;
public Integer getProcessControlDate() {
return processControlDate;
}
public void setProcessControlDate(Integer pcn) {
this.processControlDate = pcn;
}
}
Unmarshaller Method:
public static <T> T getXMLSnippetObject(String xmlString, Class<T> modelClass, XmlAdapter<?, ?> xmlAdapterObject) throws XMLStreamException, JAXBException {
JAXBContext context = JAXBContext.newInstance(modelClass);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setAdapter(xmlAdapterObject);
InputStream xmlInputStream = IOUtils.toInputStream(xmlString);
XMLInputFactory2 xmlInputFactory = (XMLInputFactory2)XMLInputFactory.newInstance();
xmlInputFactory.setProperty("javax.xml.stream.isCoalescing", true);
xmlInputFactory.setProperty("javax.xml.stream.isNamespaceAware", true);
xmlInputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", true);
xmlInputFactory.setProperty(XMLInputFactory2.P_AUTO_CLOSE_INPUT, true);
//xmlInputFactory.setProperty(XMLInputFactory2.P_DTD_OVERRIDE, false);
xmlInputFactory.setProperty(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE, false);
xmlInputFactory.setProperty(XMLInputFactory2.P_PRESERVE_LOCATION,false);
xmlInputFactory.setProperty(XMLInputFactory2.P_INTERN_NS_URIS, true);
XMLStreamReader2 xmlStreamReader = (XMLStreamReader2) xmlInputFactory.createXMLStreamReader(xmlInputStream);
T objectInstance = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(xmlStreamReader, modelClass));
return objectInstance;
}
Main Calling Class:
public class XMLparsing {
public static void main(String[] args) throws XMLStreamException, JAXBException, IOException {
String xmlString = // Xml String //
MainModelClass modelObj = null;
Integer pcnDate = 20171010;
// PCNDate & PCNDateAdapter are both no-arg-constructor classes for JAXB purpose
PCNDate pcnObj = new PCNDate();
pcnDateObj.setProcessControlDate(pcnDate);
PCNDateAdaptar pcndateAdaptar = new PCNDateAdaptar();
pcndateAdaptar.setPcnDateObject(pcnObj);
modelObj = XmlUtilsStAX.getXMLSnippetObject(xmlString, MainModelClass.class, pcndateAdaptar);
}
Result:
The whole Xml String is getting correctly parsed. Only MainModelClass's pcnDateObject is null, result & score have values. I want pcnDateObject to have 20171010.
I don't know, what I am missing, please help.
I have a list of modules in a tree like structure. The baseclass contains the childs and some generic property, while the derived class should provide it's individual fields. Now when I try to serialize this with JAXB I get only the members of the baseclass but not the ones from the derived classes.
Application.java
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Application
{
public static void main(String[] args)
{
try
{
Emulators emulators = new Emulators();
emulators.addChild(new VICEModule());
emulators.addChild(new VICEModule());
StringWriter sw = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(emulators.getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Pretty print
jaxbMarshaller.marshal(emulators, sw);
String s = sw.toString();
System.out.println(s);
}
catch(Throwable e)
{
System.err.println("Exception:"+e);
}
}
}
ModuleBase.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import com.sun.xml.internal.txw2.annotation.XmlAttribute;
public class ModuleBase
{
private List<ModuleBase> mChilds = new ArrayList<>();
private String mModuleId;
private String mModuleName;
public ModuleBase(String oModuleId, String oModuleName)
{
setModuleId(oModuleId);
setModuleName(oModuleName);
}
public void addChild(ModuleBase oModuleNode)
{
mChilds.add(oModuleNode);
}
#XmlElement(name="ModuleList")
public List<ModuleBase> getChildModules()
{
return mChilds;
}
#XmlAttribute
public String getModuleId()
{
return mModuleId;
}
public void setModuleId(String oModuleId)
{
mModuleId = oModuleId;
}
#XmlAttribute
public String getModuleName()
{
return mModuleName;
}
public void setModuleName(String oModuleName)
{
mModuleName = oModuleName;
}
}
Emulators.java
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Emulators")
public class Emulators
extends ModuleBase
{
public Emulators()
{
super("IdEmu129872q53", "Emulators");
}
}
VICEModule.java
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
#XmlRootElement(name = "VICEModule")
public class VICEModule
extends ModuleBase
{
private String mInstallationPath;
private int mPort;
public VICEModule()
{
super("Id123456", "Vice");
mPort = 6510;
}
//#XmlElement(name="InstallationPath")
#XmlValue
public String getInstallationPath()
{
return mInstallationPath;
}
public void setInstallationPath(String oPath)
{
mInstallationPath = oPath;
}
//#XmlElement(name="Port")
#XmlValue
public int getPort()
{
return mPort;
}
public void setPort(int nPort)
{
mPort = nPort;
}
}
Now when I serialize it, I get the following XML where the VICEModule values are missing and also the module is listed as ModuleList instead of VICEModule and the base fields are put as tags instead of attributes:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators>
<ModuleList>
<moduleId>Id123456</moduleId>
<moduleName>Vice</moduleName>
</ModuleList>
<ModuleList>
<moduleId>Id123456</moduleId>
<moduleName>Vice</moduleName>
</ModuleList>
<moduleId>IdEmu129872q53</moduleId>
<moduleName>Emulators</moduleName>
</Emulators>
So what this should look like is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators ModuleId="IdEmu129872q53" ModuleName="Emulators">
<VICEModule ModuleId="Id1" ModuleName="Name">
<InstallationPath>Path1</InstallationPath>
<Port>6510</Port>
</VICEModule>
<VICEModule ModuleId="Id2" ModuleName="Name">
<InstallationPath>Path2</InstallationPath>
<Port>6511</Port>
</VICEModule>
</Emulators>
When I use the VICEModule as the baseclass, then the XML looks more like it (still without the attributes though).
Writing this small demo app helped, because now I could more easily play around with the marshalling and finally got it working. I'm posting the changes here, to make this sample complete in case somebody needs it as a reference. Emulators.java was not changed, so it's not listed in the answer.
Short answer:
I had to add #XmlAnyElement(lax=true) to my getter for the child modules in order to convert the resulting XML node into a named node as I want it to. Additionally in the main application I had to traverse the tree and collect all classes that are used, so that I can pass it to the JAXBContext.
Application.java
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Application
{
public static List<Class<?>> createClasses(ModuleBase oModule)
{
List<Class<?>> classes = new ArrayList<>();
classes.add(oModule.getClass());
for(ModuleBase module : oModule.getChildModules())
{
List<Class<?>> cls = createClasses(module);
classes.addAll(cls);
}
return classes;
}
public static void main(String[] args)
{
try
{
Emulators emulators = new Emulators();
emulators.addChild(new VICEModule("Id1", "VICE V1", "V1 Path", 6510));
emulators.addChild(new VICEModule("Id2", "VICE V2", "V2 Path", 6511));
StringWriter sw = new StringWriter();
List<Class<?>> classes = createClasses(emulators);
Class<?>[] cls = new Class<?>[classes.size()];
for(int i = 0; i < classes.size(); i++)
cls[i] = classes.get(i);
JAXBContext jaxbContext = JAXBContext.newInstance(cls);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Pretty print
jaxbMarshaller.marshal(emulators, sw);
String s = sw.toString();
System.out.println(s);
}
catch(Throwable e)
{
System.err.println("Exception:"+e);
}
return;
}
}
ModuleBase.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
public class ModuleBase
{
private List<ModuleBase> mChilds = new ArrayList<>();
private String mModuleId;
private String mModuleName;
public ModuleBase(String oModuleId, String oModuleName)
{
setModuleId(oModuleId);
setModuleName(oModuleName);
}
public void addChild(ModuleBase oModuleNode)
{
mChilds.add(oModuleNode);
}
#XmlAnyElement(lax=true)
public List<ModuleBase> getChildModules()
{
return mChilds;
}
#XmlAttribute
public String getModuleId()
{
return mModuleId;
}
public void setModuleId(String oModuleId)
{
mModuleId = oModuleId;
}
#XmlAttribute
public String getModuleName()
{
return mModuleName;
}
public void setModuleName(String oModuleName)
{
mModuleName = oModuleName;
}
}
VICEModule.java
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "VICEModule")
public class VICEModule
extends ModuleBase
{
private String mInstallationPath;
private int mPort;
public VICEModule()
{
super("Id123456", "Vice");
mPort = 6510;
}
public VICEModule(String oId, String oName, String oPath, int nPort)
{
super(oId, oName);
setInstallationPath(oPath);
setPort(nPort);
}
#XmlElement(name="InstallationPath")
public String getInstallationPath()
{
return mInstallationPath;
}
public void setInstallationPath(String oPath)
{
mInstallationPath = oPath;
}
#XmlElement(name="Port")
public int getPort()
{
return mPort;
}
public void setPort(int nPort)
{
mPort = nPort;
}
}
Now the XML renders exactly as intended with storing all the objects from derived classes.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Emulators moduleId="IdEmu129872q53" moduleName="Emulators">
<VICEModule moduleId="Id1" moduleName="VICE V1">
<InstallationPath>V1 Path</InstallationPath>
<Port>6510</Port>
</VICEModule>
<VICEModule moduleId="Id2" moduleName="VICE V2">
<InstallationPath>V2 Path</InstallationPath>
<Port>6511</Port>
</VICEModule>
</Emulators>
I am trying to unmarshal a CIM file with JAXB. When any tag contains :(colon), the result is always null. If i remove the colons, then it works well.
An example of tags in my file:
Thank you.
<cim:ACLineSegment>
<cim:ACLineSegment.r>2.200000</cim:ACLineSegment.r>
<cim:ACLineSegment.x>68.200000</cim:ACLineSegment.x>
<cim:ACLineSegment.bch>0.0000829380</cim:ACLineSegment.bch>
</cim:ACLineSegment>
Java code here:
package JAXB_read;
import javax.xml.bind.annotation.*;
#XmlRootElement(name="cimACLineSegment")
#XmlAccessorType(XmlAccessType.FIELD)
public class AClineSegment {
#XmlElement(name ="cimACLineSegment.r")
private double resistance;
#XmlElement(name ="cimACLineSegment.x")
private double reactance;
#XmlElement(name ="cimACLineSegment.bch")
private double susceptance;
public double getResistance() {
return resistance;
}
public void setResistance(double resistance) {
this.resistance = resistance;
}
public double getReactance() {
return reactance;
}
public void setReactance(double reactance) {
this.reactance = reactance;
}
public double getSusceptance() {
return susceptance;
}
public void setSusceptance(double susceptance) {
this.susceptance = susceptance;
}
public AClineSegment(double resistance, double reactance, double susceptance) {
super();
this.resistance = resistance;
this.reactance = reactance;
this.susceptance = susceptance;
}
public AClineSegment() {
super();
}
}
package JAXB_read;
import java.io.File;
import javax.xml.bind.*;
public class AClineSegementJAXB {
public void unmarshall()
{
try {
JAXBContext jc = JAXBContext.newInstance(AClineSegment.class);
Unmarshaller ums = jc.createUnmarshaller();
AClineSegment ACline = (AClineSegment)ums.unmarshal(new File("src\\data\\AclineSegment.txt"));
System.out.println("Informations:");
System.out.println("----------------------");
System.out.println("Resistance: "+ACline.getResistance());
System.out.println("Reactance: "+ACline.getReactance());
System.out.println("Susceptance: "+ACline.getSusceptance());
} catch (Exception e) {
System.out.println(""+e.getMessage());
}
}
}
package Main;
import JAXB_read.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
// AC LINE SSEGMENT
public class Main {
public static void main(String[] args)
{
AClineSegementJAXB object = new AClineSegementJAXB();
object.unmarshall();
}
}
I still new in JAXB, below are my codes listing.
My intention is to print this xpath //customers/customer/name by using following sample.
I have been trying to understand from #Blaise Doughan's blogs but it keep give me empty result. Anyone can pin point where is my mistakes and what should I do?
Sample XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customers>
<customer id="100">
<name>customer1</name>
<age>29</age>
</customer>
<customer id="200">
<age>39</age>
<name>customer2</name>
</customer>
</customers>
I have Main Class
package performancetest.JAXB_Unmarshalling;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class JAXBExample {
public static void main(String[] args) {
getByCustomerName();
}
public static void getByCustomerName() {
try {
JAXBContext jc = JAXBContext.newInstance(CustomerNamesList.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
CustomerNamesList obj = (CustomerNamesList)unmarshaller.unmarshal(new File("C:\\Users\\iman.solaiman\\Documents\\file.xml"));
System.out.println(obj.getCustomers());
}catch (Exception e) {
e.printStackTrace();
}
}
}
And Customer Name List
package performancetest.JAXB_Unmarshalling;
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.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "customers")
public class CustomerNamesList {
#XmlElement(name="customer/name")
private List<CustomerNames> customerNamesList = new ArrayList<CustomerNames>();
public List<CustomerNames> getCustomers() {
return customerNamesList;
}
public void Customers(List<CustomerNames> CustomerNames) {
this.customerNamesList = CustomerNames;
}
public void getElement () {
for (int i=0; i<customerNamesList.size(); i++){
System.out.println("Element "+i+": "+customerNamesList.get(i));
}
}
}
And Customer Names
package performancetest.JAXB_Unmarshalling;
import org.eclipse.persistence.oxm.annotations.XmlPath;
public class CustomerNames {
#XmlPath("customers/customer/name/text()")
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Customer [name=" + name+ "]";
}
}
Result:
run:
[]
BUILD SUCCESSFUL (total time: 1 second)
I find that this is easier to do with the method below:
private String getXPath(String xml) throws XPathExpressionException {
String xPathResult= "";
InputSource source = new InputSource(new StringReader(xml));
XPath xpath = XPathFactory.newInstance().newXPath();
Object jaxBObject = xpath.evaluate("/customers", source, XPathConstants.NODE);
xPathResult= xpath.evaluate("name", jaxBObject);
return xPathResult;
}
This should give you the value inside the name element. I hope this is useful!