我在树状结构中有一个模块列表。基类包含子级和一些通用属性,而派生类应提供其各个字段。现在,当我尝试使用JAXB进行序列化时,我仅获得基类的成员,而没有获得派生类的成员。
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);
}
}
}
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;
}
}
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Emulators")
public class Emulators
extends ModuleBase
{
public Emulators()
{
super("IdEmu129872q53", "Emulators");
}
}
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;
}
}
现在,当我对其进行序列化时,会得到以下XML,其中缺少VICEModule值,并且该模块被列为ModuleList
而不是VICEModule
,并且基字段被放置为标签而不是属性:
<?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>
所以它应该是这样的:
<?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>
当我使用VICEModule
作为基类时,XML看起来更像它(尽管仍然没有属性)。
答案 0 :(得分:0)
编写这个小型演示应用程序很有帮助,因为现在我可以更轻松地进行编组工作并最终使它工作。我将更改发布到此处,以使此示例完整,以防万一有人需要它作为参考。 driver.switchTo().frame(driver.findElement(By.xpath(".//*@id='app']/iframe")));
未被更改,因此未在答案中列出。
简短回答:
我必须将Emulators.java
添加到子模块的getter中,以便将所需的XML节点转换为所需的命名节点。另外,在主应用程序中,我必须遍历树并收集所有使用的类,以便可以将其传递给@XmlAnyElement(lax=true)
。
JAXBContext
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;
}
}
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;
}
}
现在,XML可以完全按照预期的方式进行渲染,并存储派生类中的所有对象。
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;
}
}