我在一个由unmarshaller设置的类中有一个nillable字段:
@XmlElement(name = "value", nillable = true)
private BigDecimal valueVariable;
我的问题是我无法判断xml元素是否已被省略或设置为nil:
一个。 XML文件中缺少元素<value/>
,这不是必需的。
=&GT; (valueVariable == null)为真
B中。 XML文件包含<value xsi:nil="true"/>
=&GT; (valueVariable == null)为真
如果值为xsi:nil
或标签丢失,如何判断非String变量?
更新 你可以看到两个很好的解决方案,我更喜欢其中一个,但另一个也没关系!
答案 0 :(得分:5)
JAXB(JSR-222)实现可以将null
表示为基于nillable
@XmlElement
上的JAXBElement
设置的缺席节点或可终止元素。当您需要同时支持两者或区分两者时,您可以利用JAXBElement
。
<强>根强>
@XmlElementRef
类型的字段/属性与@XmlElementDecl
注释一起映射。这对应于使用@XmlRegistry
注释的类的import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementRef(name="foo")
JAXBElement<BigDecimal> foo;
@XmlElementRef(name="bar")
JAXBElement<BigDecimal> bar;
@XmlElementRef(name="baz")
JAXBElement<BigDecimal> baz;
}
注释。
import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name = "foo")
public JAXBElement<BigDecimal> createFoo(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("foo"), BigDecimal.class, value);
}
@XmlElementDecl(name = "bar")
public JAXBElement<BigDecimal> createBar(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, value);
}
@XmlElementDecl(name = "baz")
public JAXBElement<BigDecimal> createBaz(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("baz"), BigDecimal.class, value);
}
}
<强>的ObjectFactory 强>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>
<强> input.xml中强>
JAXBIntrospector
<强>演示强>
下面是一些可以运行的演示代码,以显示一切正常。请注意JAXBElement
如何在必要时用import java.io.File;
import java.math.BigDecimal;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18440987/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
nullOrAbsent("foo", root.foo);
nullOrAbsent("bar", root.bar);
nullOrAbsent("baz", root.baz);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
private static void nullOrAbsent(String property, JAXBElement<BigDecimal> value) {
System.out.print(property);
if(null == value) {
System.out.print(": ABSENT - ");
} else if(value.isNil()) {
System.out.print(": NIL - ");
} else {
System.out.print(": VALUE - ");
}
System.out.println(JAXBIntrospector.getValue(value));
}
}
展开实际价值。
foo: ABSENT - null
bar: NIL - null
baz: VALUE - 123.456
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>
<强>输出强>
public BigDecimal getBar() {
if(null == bar) {
return null;
}
return bar.getValue();
}
public void setBar(BigDecimal bar) {
if(null == this.bar) {
this.bar = new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, bar);
} else {
this.bar.setValue(bar);
}
}
<强>更新强>
如果您想维护现有的get / set方法,那么您可以像我在本答案中那样保持字段访问权限,并将访问者方法更改为如下所示:
isSet
此外,您可以添加public boolean isSetBar() {
return null != bar;
}
方法以查看该值是否已设置。
Unmarshaller
此方法不要求您有权访问ObjectFactory
。要确保选择@XmlSeeAlso
,您可以使用@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(ObjectFactory.class)
public class Root {
注释从您的某个域类引用它。
{{1}}
答案 1 :(得分:1)
这里有一个类似的问题:Handling missing nodes with JAXB。似乎如果缺少元素,则不会调用setter方法。因此,您可以在方法中放置一些逻辑来确定节点是否缺失或具有空值。
@XmlElement(name = "value", nillable = true)
private BigDecimal valueVariable;
private boolean valueVariableMissing = true;
public void setValueVariable(BigDecimal valueVariable){
this.valueVariable = valueVariable;
this.valueVariableMissing = false;
}
答案 2 :(得分:0)
我正在处理同样的问题,
为了修复它,我在包中创建了一个新文件,我正在整理对象:
“package-info.java”
我在那里补充道:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://the.correct.namespace.com/gateway/", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.the.package.name;
现在一切正常