2009-11-26 58 views
2

我有一个XML架构:JAXB minOccurs = 0。元素是否存在?

<xsd:element name="Person"> 
<xsd:complexType> 
    <xsd:sequence> 
    <xsd:element name="name" type="xsd:string" /> 
    <xsd:element name="lat" type="xsd:double" minOccurs="0"/> 
    <xsd:element name="lon" type="xsd:double" minOccurs="0"/> 
    </xsd:sequence> 
</xsd:complexType> 
</xsd:element> 

而且我有一个XML消息:

<Person> 
<name>Fred</name> 
</Person> 

我使用JAXB自动生成我的课(即Person.java等)。

所以在运行时我使用JAXB解组以上的XML消息,并得到一个Person对象实例。当我做一个p.getLat()p.getLon()的返回值都是0.0,即使原始的XML不包含<lat><lon>元素。

是什么让这个糟糕的是,0.0,0.0是一个有效的经度和纬度。一个人很少会在那里找到,但那不是重点!

在IBM站点中的article使用附加的XML元素作为元数据来明确陈述可选元素是否存在建议。即

<xsd:element name="hasLat" type="xsd:boolean"/> 
<xsd:element name="hasLon" type="xsd:boolean"/> 

所以上面的XML消息将成为:

<Person> 
<name>Fred</name> 
<hasLat>false</hasLat> 
<hasLon>false</hasLon> 
</Person> 

这似乎是一个丑陋的黑客。 JAXB必须有一个合适的方法来检查元素是否存在,以便我可以信任来自我的getLat()getLon()的返回值?

+0

您是使用Java 6中的JAXB还是使用1.5的独立库? JAXB如何生成类的方式发生了变化。特别是对于数组。尝试最新的一个。 – 2009-11-27 02:31:00

+0

我使用JAXME(在Fedora上的软件包是ws-jaxme-0.5.1-3.4.fc11.noarch)和Java 6(java-1.6.0-openjdk-1.6.0.0-30.b16.fc11.i586) 。 – 2009-11-27 21:26:40

+0

这似乎是JAXB 2.0的JAXME实现的一个特别问题。切换到Sun的实现时,如果元素未包含在XML消息中,getter将返回空值。 – 2009-11-30 20:45:38

回答

4

我根本没有看到这个问题。对于我xjc生成Person类与性质latlonDouble类型。

如果我解组没有<lat><lon>元素的XML文件,然后将所得的物体Person具有这些属性null值,如我期望。

我不知道你是怎么得到0.0任何地方。

我的XML模式:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://www.example.com/person"> 
<xsd:element name="Person"> 
    <xsd:complexType> 
    <xsd:sequence> 
    <xsd:element name="name" type="xsd:string" /> 
    <xsd:element name="lat" type="xsd:double" minOccurs="0"/> 
    <xsd:element name="lon" type="xsd:double" minOccurs="0"/> 
    </xsd:sequence> 
    </xsd:complexType> 
</xsd:element> 
</xsd:schema> 

Test.java

import com.example.person.Person; 
import javax.xml.bind.JAXB; 
import java.io.File; 

public class Test { 
    public static void main(String[] args) { 
    Person p = JAXB.unmarshal(new File("foo.xml"), Person.class); 
    System.out.println(p.getName()); 
    System.out.println(p.getLat()); 
    System.out.println(p.getLon()); 
    } 
} 

我:

<Person> 
<name>Fred</name> 
<lat>1.0</lat> 
</Person> 

输出:

Fred 
1.0 
null 
+2

我刚刚尝试过您的示例,并按您的建议工作。这是个好消息!这不是JAXB的限制,而是我的项目的一个问题。谢谢! – 2009-11-27 21:35:32

0

获得0.0返回vs null的最可能原因是使用Double基本类型或Double对象类型。如果值为空,Double基元将默认为0.0,因为null对于基元类型不是有效值。 Double对象将允许您为这些字段分配一个空值。在你的Person类中的高峰可能会揭示这一点。

+1

是的,我认为你是对的双重对双。然而,问题似乎源于JAXME将xsd:double转换为java原语double,Sun Java JAXB将xsd:double转换为java Double。 JAXME创建的代码无法检查是否设置了XML中的值。检查0.0是不可取的,因为0.0是经度和纬度的有效值。我已经切换到使用JAXB,以便我可以检查null以确定元素是否提供。 – 2010-06-03 14:10:00