Java 使用混合类型时,封送的XML没有子级
我正在尝试解组存储在数据库中的XML CLOB。根据标准,序列可以包含属性以及子序列。引用的一个示例是属性 因此,我在JAXB DTO中使用Java 使用混合类型时,封送的XML没有子级,java,xml,jaxb,Java,Xml,Jaxb,我正在尝试解组存储在数据库中的XML CLOB。根据标准,序列可以包含属性以及子序列。引用的一个示例是属性 因此,我在JAXB DTO中使用@XmlMixed来处理子属性也可能是序列的情况。但是,在编组未编组的XML时,结果输出只是根元素,没有子元素 下面是表示上述内容序列的输入XML <Root> <ps> <p name="0040A010" vt="8">HAS CONCEPT MOD</p> <p name="00
@XmlMixed
来处理子属性也可能是序列的情况。但是,在编组未编组的XML时,结果输出只是根元素,没有子元素
下面是表示上述内容序列的输入XML
<Root>
<ps>
<p name="0040A010" vt="8">HAS CONCEPT MOD</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121049</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Language of Content Item and Descendants
</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">eng</p>
<p name="00080102" vt="8">ISO639_2</p>
<p name="00080104" vt="8">English</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121005</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Observer Type</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">121006</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">PNAME</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121008</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person Observer Name</p>
</ps>
</p>
<p name="0040A123" vt="8">IMAGE</p>
</ps>
<ps>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.4</p>
<p name="00081155" vt="8">1.3.6.1.4.1.5962.99.1.3923360762.207819601.1541521685498.13.0
</p>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.11.1</p>
<p name="00081155" vt="8">1.2.840.114356.2019.12.115.113.18.116.1508.6
</p>
</ps>
</p>
<p name="00750010" vt="8">GEIIS_IW</p>
<p name="007510A1" vt="8">1</p>
</ps>
</p>
<p name="0040A010" vt="8">CONTAINS</p>
<p name="0040A040" vt="8">IMAGE</p>
</ps>
</Root>
输出
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root/>
XmlMixed&xmlementref
即使使用xmlementref
我们也无法将值反序列化为PropertySequence
或String
。无论如何,使用JAXBElement
会容易得多。让我们看看模型:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Root", propOrder = {"ps"})
public class Root {
protected List<PropertySequence> ps;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ps", propOrder = {"p"})
public class PropertySequence {
protected List<Property> p;
public List<Property> getP() {
if (p == null) {
p = new ArrayList<>();
}
return this.p;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (Property property : p) {
builder.append(property).append(System.lineSeparator());
}
return builder.toString();
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "p", propOrder = {"content"})
public class Property {
@XmlMixed
@XmlElementRef(name = "ps", type = JAXBElement.class, required = false)
protected List<Serializable> content;
@XmlAttribute(name = "name")
protected String name;
@XmlAttribute(name = "vt")
protected String vt;
@XmlTransient
public String getStringValue() {
if (content != null && content.size() == 1) {
return content.get(0).toString();
}
return null;
}
@XmlTransient
public PropertySequence getPropertySequence() {
if (content != null && content.size() == 3) {
return ((JAXBElement<PropertySequence>) content.get(1)).getValue();
}
return null;
}
public List<Serializable> getContent() {
if (content == null) {
content = new ArrayList<>();
}
return this.content;
}
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getVt() {
return vt;
}
public void setVt(String value) {
this.vt = value;
}
@Override
public String toString() {
Object value = getStringValue();
if (value == null) {
value = getPropertySequence();
}
return "Property{" +
"content=" + value +
", name='" + name + '\'' +
", vt='" + vt + '\'' +
'}';
}
}
@XmlRegistry
public class ObjectFactory {
private final static QName ROOT_QNAME = new QName("", "Root");
private final static QName PropertySequence_QNAME = new QName("", "ps");
@XmlElementDecl(namespace = "", name = "Root")
public JAXBElement<Root> createRoot(Root value) {
return new JAXBElement<>(ROOT_QNAME, Root.class, null, value);
}
@XmlElementDecl(namespace = "", name = "ps", scope = Property.class)
public JAXBElement<PropertySequence> createPropertySequence(PropertySequence value) {
return new JAXBElement<>(PropertySequence_QNAME, PropertySequence.class, Property.class, value);
}
}
XmlMixed&xmlanyement
它打印空根,因为反序列化不能正确地用于映射,并且根对象为空(propertySequence
isnull
)。您需要更新POJO
映射。使用@xmlanyementref
注释代替@xmlanyement
。经过少量更改后的模型可能如下所示:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Root")
class Root {
@XmlElement(required = true, name = "ps")
protected List<PropertySequence> propertySequence;
// getters, setters, toString
}
@XmlAccessorType(XmlAccessType.FIELD)
class PropertySequence {
@XmlElement(name = "p")
protected List<Property> property;
// getters, setters, toString
}
@XmlAccessorType(XmlAccessType.FIELD)
class Property {
@XmlAttribute(name = "name", required = true)
protected String name;
@XmlAttribute(name = "vt", required = true)
protected Integer vt;
@XmlMixed
@XmlAnyElement
protected List<Object> value;
// getters, setters, toString
}
打印对象:
Root{propertySequence=[PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS CONCEPT MOD]}, Property{name='0040A040', vt=8, value=[CODE]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A168', vt=8, value=[
, [ps: null],
]}]}, PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS OBS CONTEXT]}, Property{name='0040A040', vt=8, value=[CODE]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A168', vt=8, value=[
, [ps: null],
]}]}, PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS OBS CONTEXT]}, Property{name='0040A040', vt=8, value=[PNAME]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A123', vt=8, value=[IMAGE]}]}, PropertySequence{property=[Property{name='00081199', vt=8, value=[
, [ps: null],
]}, Property{name='0040A010', vt=8, value=[CONTAINS]}, Property{name='0040A040', vt=8, value=[IMAGE]}]}]}
和XML
:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<ps>
<p name="0040A010" vt="8">HAS CONCEPT MOD</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121049</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Language of Content Item and Descendants</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">eng</p>
<p name="00080102" vt="8">ISO639_2</p>
<p name="00080104" vt="8">English</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121005</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Observer Type</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">121006</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">PNAME</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121008</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person Observer Name</p>
</ps>
</p>
<p name="0040A123" vt="8">IMAGE</p>
</ps>
<ps>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.4</p>
<p name="00081155" vt="8">1.3.6.1.4.1.5962.99.1.3923360762.207819601.1541521685498.13.0
</p>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.11.1</p>
<p name="00081155" vt="8">1.2.840.114356.2019.12.115.113.18.116.1508.6
</p>
</ps>
</p>
<p name="00750010" vt="8">GEIIS_IW</p>
<p name="007510A1" vt="8">1</p>
</ps>
</p>
<p name="0040A010" vt="8">CONTAINS</p>
<p name="0040A040" vt="8">IMAGE</p>
</ps>
</Root>
具有概念模型
代码
121049
DCM
内容项及其子体的语言
工程
ISO639\U 2
英语
具有OBS上下文
代码
121005
DCM
观察员类型
121006
DCM
人
具有OBS上下文
PNAME
121008
DCM
观察者姓名
图像
1.2.840.10008.5.1.4.1.1.4
1.3.6.1.4.1.5962.99.1.3923360762.2078119601.1541521685498.13.0
1.2.840.10008.5.1.4.1.1.11.1
1.2.840.114356.2019.12.115.113.18.116.1508.6
GEIS\u IW
1
包含
图像
解组只是为了测试绑定。但是,如果我们看到System.out
,嵌套序列将显示null-属性{name='0040A168',vt=8,value=[,[ps:null],]
。如何捕获嵌套序列并递归读取它?
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Root", propOrder = {"ps"})
public class Root {
protected List<PropertySequence> ps;
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ps", propOrder = {"p"})
public class PropertySequence {
protected List<Property> p;
public List<Property> getP() {
if (p == null) {
p = new ArrayList<>();
}
return this.p;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (Property property : p) {
builder.append(property).append(System.lineSeparator());
}
return builder.toString();
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "p", propOrder = {"content"})
public class Property {
@XmlMixed
@XmlElementRef(name = "ps", type = JAXBElement.class, required = false)
protected List<Serializable> content;
@XmlAttribute(name = "name")
protected String name;
@XmlAttribute(name = "vt")
protected String vt;
@XmlTransient
public String getStringValue() {
if (content != null && content.size() == 1) {
return content.get(0).toString();
}
return null;
}
@XmlTransient
public PropertySequence getPropertySequence() {
if (content != null && content.size() == 3) {
return ((JAXBElement<PropertySequence>) content.get(1)).getValue();
}
return null;
}
public List<Serializable> getContent() {
if (content == null) {
content = new ArrayList<>();
}
return this.content;
}
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getVt() {
return vt;
}
public void setVt(String value) {
this.vt = value;
}
@Override
public String toString() {
Object value = getStringValue();
if (value == null) {
value = getPropertySequence();
}
return "Property{" +
"content=" + value +
", name='" + name + '\'' +
", vt='" + vt + '\'' +
'}';
}
}
@XmlRegistry
public class ObjectFactory {
private final static QName ROOT_QNAME = new QName("", "Root");
private final static QName PropertySequence_QNAME = new QName("", "ps");
@XmlElementDecl(namespace = "", name = "Root")
public JAXBElement<Root> createRoot(Root value) {
return new JAXBElement<>(ROOT_QNAME, Root.class, null, value);
}
@XmlElementDecl(namespace = "", name = "ps", scope = Property.class)
public JAXBElement<PropertySequence> createPropertySequence(PropertySequence value) {
return new JAXBElement<>(PropertySequence_QNAME, PropertySequence.class, Property.class, value);
}
}
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
JAXBElement<Root> root = (JAXBElement<Root>) unmarshaller.unmarshal(xmlFile);
System.out.println(root.getValue());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(root, System.out);
}
}
RootType{ps=[Property{content=HAS CONCEPT MOD, name='0040A010', vt='8'}
Property{content=CODE, name='0040A040', vt='8'}
Property{content=Property{content=121049, name='00080100', vt='8'}
Property{content=DCM, name='00080102', vt='8'}
Property{content=Language of Content Item and Descendants, name='00080104', vt='8'}
, name='0040A043', vt='8'}
Property{content=Property{content=eng, name='00080100', vt='8'}
Property{content=ISO639_2, name='00080102', vt='8'}
Property{content=English, name='00080104', vt='8'}
, name='0040A168', vt='8'}
, Property{content=HAS OBS CONTEXT, name='0040A010', vt='8'}
Property{content=CODE, name='0040A040', vt='8'}
Property{content=Property{content=121005, name='00080100', vt='8'}
Property{content=DCM, name='00080102', vt='8'}
Property{content=Observer Type, name='00080104', vt='8'}
, name='0040A043', vt='8'}
Property{content=Property{content=121006, name='00080100', vt='8'}
Property{content=DCM, name='00080102', vt='8'}
Property{content=Person, name='00080104', vt='8'}
, name='0040A168', vt='8'}
, Property{content=HAS OBS CONTEXT, name='0040A010', vt='8'}
Property{content=PNAME, name='0040A040', vt='8'}
Property{content=Property{content=121008, name='00080100', vt='8'}
Property{content=DCM, name='00080102', vt='8'}
Property{content=Person Observer Name, name='00080104', vt='8'}
, name='0040A043', vt='8'}
Property{content=IMAGE, name='0040A123', vt='8'}
, Property{content=Property{content=1.2.840.10008.5.1.4.1.1.4, name='00081150', vt='8'}
Property{content=1.3.6.1.4.1.5962.99.1.3923360762.207819601.1541521685498.13.0
, name='00081155', vt='8'}
Property{content=Property{content=1.2.840.10008.5.1.4.1.1.11.1, name='00081150', vt='8'}
Property{content=1.2.840.114356.2019.12.115.113.18.116.1508.6
, name='00081155', vt='8'}
, name='00081199', vt='8'}
Property{content=GEIIS_IW, name='00750010', vt='8'}
Property{content=1, name='007510A1', vt='8'}
, name='00081199', vt='8'}
Property{content=CONTAINS, name='0040A010', vt='8'}
Property{content=IMAGE, name='0040A040', vt='8'}
]}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Root")
class Root {
@XmlElement(required = true, name = "ps")
protected List<PropertySequence> propertySequence;
// getters, setters, toString
}
@XmlAccessorType(XmlAccessType.FIELD)
class PropertySequence {
@XmlElement(name = "p")
protected List<Property> property;
// getters, setters, toString
}
@XmlAccessorType(XmlAccessType.FIELD)
class Property {
@XmlAttribute(name = "name", required = true)
protected String name;
@XmlAttribute(name = "vt", required = true)
protected Integer vt;
@XmlMixed
@XmlAnyElement
protected List<Object> value;
// getters, setters, toString
}
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(xmlFile);
System.out.println(root);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(root, System.out);
}
}
Root{propertySequence=[PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS CONCEPT MOD]}, Property{name='0040A040', vt=8, value=[CODE]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A168', vt=8, value=[
, [ps: null],
]}]}, PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS OBS CONTEXT]}, Property{name='0040A040', vt=8, value=[CODE]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A168', vt=8, value=[
, [ps: null],
]}]}, PropertySequence{property=[Property{name='0040A010', vt=8, value=[HAS OBS CONTEXT]}, Property{name='0040A040', vt=8, value=[PNAME]}, Property{name='0040A043', vt=8, value=[
, [ps: null],
]}, Property{name='0040A123', vt=8, value=[IMAGE]}]}, PropertySequence{property=[Property{name='00081199', vt=8, value=[
, [ps: null],
]}, Property{name='0040A010', vt=8, value=[CONTAINS]}, Property{name='0040A040', vt=8, value=[IMAGE]}]}]}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root>
<ps>
<p name="0040A010" vt="8">HAS CONCEPT MOD</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121049</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Language of Content Item and Descendants</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">eng</p>
<p name="00080102" vt="8">ISO639_2</p>
<p name="00080104" vt="8">English</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">CODE</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121005</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Observer Type</p>
</ps>
</p>
<p name="0040A168" vt="8">
<ps>
<p name="00080100" vt="8">121006</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person</p>
</ps>
</p>
</ps>
<ps>
<p name="0040A010" vt="8">HAS OBS CONTEXT</p>
<p name="0040A040" vt="8">PNAME</p>
<p name="0040A043" vt="8">
<ps>
<p name="00080100" vt="8">121008</p>
<p name="00080102" vt="8">DCM</p>
<p name="00080104" vt="8">Person Observer Name</p>
</ps>
</p>
<p name="0040A123" vt="8">IMAGE</p>
</ps>
<ps>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.4</p>
<p name="00081155" vt="8">1.3.6.1.4.1.5962.99.1.3923360762.207819601.1541521685498.13.0
</p>
<p name="00081199" vt="8">
<ps>
<p name="00081150" vt="8">1.2.840.10008.5.1.4.1.1.11.1</p>
<p name="00081155" vt="8">1.2.840.114356.2019.12.115.113.18.116.1508.6
</p>
</ps>
</p>
<p name="00750010" vt="8">GEIIS_IW</p>
<p name="007510A1" vt="8">1</p>
</ps>
</p>
<p name="0040A010" vt="8">CONTAINS</p>
<p name="0040A040" vt="8">IMAGE</p>
</ps>
</Root>