使用JAXB使用namspace解组XML时为空值

时间:2013-02-21 15:12:01

标签: java jaxb unmarshalling

使用JAXB解组简单XML(CSDL的子集)时遇到问题 过去曾有人试图帮助我(here),但是部分工作,我不知道该怎么办...... 请考虑以下XML:

<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
  <edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0">
    <Schema xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:sap="http://www.sap.com/Protocols/SAPData" xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="myNS">
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

据我所知,我有一个 package-info.java 文件,看起来像(在同一个包中):

@XmlSchema(
  namespace="http://schemas.microsoft.com/ado/2007/06/edmx",
  elementFormDefault=XmlNsForm.QUALIFIED,
  xmlns={
          @XmlNs(prefix="edmx", namespaceURI="http://schemas.microsoft.com/ado/2007/06/edmx"),
          @XmlNs(prefix="", namespaceURI="http://schemas.microsoft.com/ado/2009/11/edm"),
          @XmlNs(prefix="m", namespaceURI="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata")                                
  }
)
@XmlAccessorType(XmlAccessType.FIELD)
package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;

import javax.xml.bind.annotation.*;

另外,我有以下数据结构:

Edmx.java

package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Edmx")
public class Edmx {

    @XmlElement(name = "DataServices")
    private DataService dataService;

    public DataService getDataService() {
          return dataService;
    }
}

DataService.java

package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class DataService {

    @XmlElement(name = "Schema")
    private Schema schema;

    @XmlAttribute(name = "DataServiceVersion")
    private double version;

    public Schema getSchema() {
      return schema;
    }
 }

Schema.java

package com.sap.ndb.studio.rdl.csdlparser.jaxb.objects;

@XmlRootElement
public class Schema {
  ....
}

注意:在Schema.java中我有一些与XML无关的实现,所以我把它取下来了(内部逻辑)。

在使用JAXB解组XML之后,返回的Edmx对象在'schema'和'version'成员中都包含空值,尽管我在package-info.java中提到了所有xmlns参数。

任何人? :(

1 个答案:

答案 0 :(得分:0)

<强>更新

在我对你之前的一个问题的回答中,我从这个问题中提供了该模型的映射。

我已更新此答案,以解决您所做的以下评论:

  

我为什么要申报   '命名空间= schemas.microsoft.com / ADO / 2009/11 / EDM';在我的@XmlElement中?   对不起烦恼(这是我第一次使用JAXB)但是我   只需要一个很长的XML,许多@XmlElement节点类似于   'Schema',我想仅为它们声明命名空间   一旦...

通过根据模型类对应的命名空间将模型类组织到不同的包中,可以减少声明命名空间所需的次数。

命名空间http://schemas.microsoft.com/ado/2007/06/edmx

的包1

<强> 包信息

对于每个包,我们将使用@XmlSchema注释来指定命名空间限定。在此示例中,我们只需要为此特定包指定命名空间。

@XmlSchema(
        namespace="http://schemas.microsoft.com/ado/2007/06/edmx",
        elementFormDefault=XmlNsForm.QUALIFIED,
        xmlns={
                @XmlNs(
                    prefix="edmx", 
                    namespaceURI="http://schemas.microsoft.com/ado/2007/06/edmx"
                ),
        }
)
@XmlAccessorType(XmlAccessType.FIELD)
package forum14875956.edmx;

import javax.xml.bind.annotation.*;

<强> EDMX

对应于Edmx类的XML元素将根据我们在此包的@XmlSchema注释上定义的内容进行命名空间限定。

package forum14875956.edmx;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "Edmx")
public class Edmx {

    @XmlElement(name = "DataServices")
    private DataService dataService;

    public DataService getDataService() {
        return dataService;
    }

}

<强> 的DataService

DataService类包含对与不同XML命名空间对应的类的引用。如果Schema类在同一个包中,我们可以使用@XmlElement注释来覆盖命名空间限定。由于Schema位于不同的包中,因此我们可以使用@XmlElementRef注释。这告诉JAXB从为该类配置的根元素派生元素信息。

package forum14875956.edmx;

import javax.xml.bind.annotation.*;
import forum14875956.schema.Schema;

public class DataService {

    //@XmlElement(namespace="http://schemas.microsoft.com/ado/2009/11/edm", name="Schema")
    @XmlElementRef
    private Schema schema;

    public Schema getSchema() {
        return schema;
    }

}

名称空间http://schemas.microsoft.com/ado/2009/11/edm

的套餐2

我们将再次使用@XmlSchema来声明第二个包的名称空间信息。

<强> 包信息

@XmlSchema(
        namespace="http://schemas.microsoft.com/ado/2009/11/edm",
        elementFormDefault=XmlNsForm.QUALIFIED,
        xmlns={
                @XmlNs(
                    prefix="", 
                    namespaceURI="http://schemas.microsoft.com/ado/2009/11/edm"
                )
        }
)
@XmlAccessorType(XmlAccessType.FIELD)
package forum14875956.schema;

import javax.xml.bind.annotation.*;

<强> 模式

Schema类中的元素将是其包的@XmlSchema注释中基于命名空间限定的命名空间信息。

package forum14875956.schema;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Schema")
public class Schema {

}

原始回答

您需要在schema属性的映射中包含名称空间URI:

@XmlRootElement
public class DataService {

    @XmlElement(name = "Schema" , namespace="http://schemas.microsoft.com/ado/2009/11/edm")
    private Schema schema;

    @XmlAttribute(name = "DataServiceVersion")
    private double version;

    public Schema getSchema() {
      return schema;
    }
 }

完整示例

我前一段时间我回答了你的一个问题,提供了这个模型的完整映射: