2012-01-10 5 views
2

У меня возникла странная проблема с JAXB. Я использовал xjc для генерации моих классов java из своего XSD, и все выглядит хорошо. Если я использую schemagen, он создает правильную схему, которая соответствует моему первоначальному xsd. Однако, если я использую JAXBContext.generateSchema(), то сгенерированная схема является неполной.jaxbcontext генерирует неполные схемы?

Я использую Oracle Java 1.6.0_29 и jaxb-2.2.4-1.jar как реализацию. Я включаю java-код (который генерирует схему) и xsd ниже, а также вывод вызова jaxb.

CalculateBorrowingDataResponse.xsd:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema 
    version="1.1" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified" 
    targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:lssSt="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:cbdRes="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 


    <!-- CalculateBorrowingData --> 
    <xsd:complexType name="CalculateBorrowingDataResponseType"> 
     <xsd:sequence> 
      <xsd:element name="loanAgmt" type="cbdRes:LoanAgreementType" minOccurs="1" maxOccurs="1" /> 
     </xsd:sequence> 
    </xsd:complexType> 


    <xsd:complexType name="LoanAgreementType"> 
     <xsd:sequence> 
      <xsd:element name="borrowingBasedPmtAmt" type="lssSt:borrowingBasedPmtAmt" minOccurs="0" maxOccurs="1" /> 
      <xsd:element name="maxPmtAmt" type="lssSt:maxPmtAmt" minOccurs="0" maxOccurs="1" /> 
      <xsd:element name="borrowingCapacityMin" type="lssSt:borrowingCapacityMin" minOccurs="0" maxOccurs="1" /> 
      <xsd:element name="borrowingCapacityMax" type="lssSt:borrowingCapacityMax" minOccurs="0" maxOccurs="1" /> 
      <xsd:element name="propertyValueMinAmt" type="lssSt:propertyValueMinAmt" minOccurs="0" maxOccurs="1" /> 
      <xsd:element name="propertyValueMaxAmt" type="lssSt:propertyValueMaxAmt" minOccurs="0" maxOccurs="1" /> 
     </xsd:sequence> 
    </xsd:complexType> 

    <xsd:element name="calculateBorrowingDataResponse" type="cbdRes:CalculateBorrowingDataResponseType"/> 


    <xsd:simpleType name="borrowingBasedPmtAmt"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 
    <xsd:simpleType name="maxPmtAmt"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 
    <xsd:simpleType name="borrowingCapacityMin"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 
    <xsd:simpleType name="borrowingCapacityMax"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 
    <xsd:simpleType name="propertyValueMinAmt"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 
    <xsd:simpleType name="propertyValueMaxAmt"> 
     <xsd:restriction base="xsd:decimal" > 
     <xsd:totalDigits value="19" /> 
     <xsd:fractionDigits value="4" /> 
     </xsd:restriction> 
    </xsd:simpleType> 

</xsd:schema> 

Java код:

// Creating the XML tree 
    JAXBContext jc = JAXBContext.newInstance(CalculateBorrowingDataResponseType.class); 
    Unmarshaller u = jc.createUnmarshaller(); 

    // generate the schemas 
    final List<ByteArrayOutputStream> schemaStreams = new ArrayList<ByteArrayOutputStream>(); 
    jc.generateSchema(new SchemaOutputResolver(){ 
     @Override 
     public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { 
      ByteArrayOutputStream out = new ByteArrayOutputStream(); 
      schemaStreams.add(out); 
      StreamResult streamResult = new StreamResult(out); 
      streamResult.setSystemId(""); 
      return streamResult; 
     }}); 

    // convert to a list of string 
    List<String> schemas = new ArrayList<String>(); 
    for(ByteArrayOutputStream os : schemaStreams) 
    { 
     schemas.add(os.toString()); 
     System.out.println(os.toString()); 
    } 

Выход jaxbContext.generateSchema():

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" xmlns:tns="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:complexType name="CalculateBorrowingDataResponseType"> 
    <xs:sequence> 
     <xs:element name="loanAgmt" type="tns:LoanAgreementType"/> 
    </xs:sequence> 
    </xs:complexType> 

    <xs:complexType name="LoanAgreementType"> 
    <xs:sequence> 
     <xs:element name="borrowingBasedPmtAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="maxPmtAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="borrowingCapacityMin" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="borrowingCapacityMax" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="propertyValueMinAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="propertyValueMaxAmt" type="xs:decimal" minOccurs="0"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Как вы можете видеть, выход схемы соответствует очень внимательно, сохраняйте и за исключением того, что отсутствует определение элемента calculateBorrowingDataResponse! Однако, если я использую схему, генерируется calculateBorrowingDataResponse.

Я пропустил что-то в своей настройке SchemaOutputResolver или сделал что-то неправильное/неполное? Или это ошибка в Jaxb RI?

ответ

6

Изменить

JAXBContext.newInstance(CalculateBorrowingDataResponseType.class); 

в

JAXBContext.newInstance(CalculateBorrowingDataResponseType.class.getPackage().getName()); 

JAXB нуждается в информации, определенной в файле package-info.java (генерируемой xjc из вашего XSD) в пакете выше класса.

Это не создает элемент XSD, о котором идет речь, потому что CalculateBorrowingDataResponseType не содержит аннотации @XmlRootElement.

Почему не xjc создать его с самого начала? См. the most authoritative explanation on the Internets regarding this matter.

И почему ваш код генерирует вышеупомянутый элемент, если вы укажете имя пакета до JAXBContext.newInstance(...), хотя CalculateBorrowingDataResponseType все еще отсутствует @XmlRootAnnotation? У меня нет ни малейшего понятия! Now I have!

+0

Удивительный! Спасибо за быстрый ответ. Несмотря на то, что я несколько раз читал документы, я все же ожидал, что JAXB проведет проверку содержащего пакета для связанных файлов ObjectFactory() и файлов пакета. Изменение его имени пакета работало как рекламируемое. –

+1

+1 - Я также добавил ответ, объясняющий, что это класс 'ObjectFactory', который отвечает за создание этого элемента в схеме XML. Ваш подход - один из способов сделать это, другой - включить «ObjectFactory» в классы, используемые для начальной загрузки JAXBContext: http://stackoverflow.com/a/8810207/383861 –

+0

@BlaiseDoughan Я предпочитаю не включать 'ObjectFactory 'классы в' JAXBContext.newInstance (...) ', потому что, если у меня есть несколько генерируемых XJC пакетов, между ними возникает конфликт пространства имен. +1 для _find_ и объяснения! –

0

Почему вы думаете, что в схеме roundrip 'schema1-> XJC-> schema2' schema1 и схеме 2 должно быть одинаково? У вас есть класс Java, сгенерированный для элемента «calculateBorrowingDataResponse» XJC? Я так не думаю - как бы вы ожидали, что это будет в сгенерированной схеме?

+0

_DO вы Java класс, сгенерированные для 'calculateBorrowingDataResponse' от XJC? _ У него действительно есть 'Calcul ateBorrowingDataResponseType.class', поскольку он сначала компилирует 'CalculateBorrowingDataResponse.xsd' с' xjc'. Я не вижу смысла в создании классов из схемы, а затем генерирую схему из сгенерированных классов, но кого я должен судить? –

+0

Ну, Тип отличается от Element. У него есть класс для типа, но не для элемента из схемы. – maximdim

+0

@maximdim. Нет - вы правы. У меня нет класса java для сгенерированного элемента. Однако, если схемагенерация может создать правильный xsd из файла CalculateBorrowingDataResponseType.class, я, естественно, предположил, что jaxb.generateSchema() также сможет. –

5

Следующие из сгенерированных ObjectFactory класса, что вызывает этот элемент, чтобы быть сгенерировано:

@XmlElementDecl(namespace = "http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse", name = "calculateBorrowingDataResponse") 
public JAXBElement<CalculateBorrowingDataResponseType> createCalculateBorrowingDataResponse(CalculateBorrowingDataResponseType value) { 
    return new JAXBElement<CalculateBorrowingDataResponseType>(_CalculateBorrowingDataResponse_QNAME, CalculateBorrowingDataResponseType.class, null, value); 
} 

Для того, чтобы иметь ObjectFactory класса обрабатываемого вами либо JAXBContext нужно включены в массиве классов прошло создать JAXBContext:

JAXBContext jc = JAXBContext.newInstance(CalculateBorrowingDataResponseType.class, ObjectFactory.class); 

Или создать JAXBContext на имя пакета сгенерированных сл ослы:

String contextPath = CalculateBorrowingDataResponseType.class.getPackage().getName(); 
JAXBContext jc = JAXBContext.newInstance(contextPath); 

Полный пример

package forum8809406; 

import java.io.IOException; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.SchemaOutputResolver; 
import javax.xml.transform.Result; 
import javax.xml.transform.stream.StreamResult; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance("forum8809406"); 
     jc.generateSchema(new SOR()); 
    } 

    private static class SOR extends SchemaOutputResolver { 

     @Override 
     public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException { 
      StreamResult result = new StreamResult(System.out); 
      result.setSystemId(suggestedFileName); 
      return result; 
     } 

    } 

} 

Я получаю следующее генерируется XML-схема, которая содержит calculateBorrowingDataResponse элемент:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<xs:schema 
    version="1.0" 
    elementFormDefault="qualified" 
    targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:tns="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:complexType name="CalculateBorrowingDataResponseType"> 
    <xs:sequence> 
     <xs:element name="loanAgmt" type="tns:LoanAgreementType"/> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="LoanAgreementType"> 
    <xs:sequence> 
     <xs:element name="borrowingBasedPmtAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="maxPmtAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="borrowingCapacityMin" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="borrowingCapacityMax" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="propertyValueMinAmt" type="xs:decimal" minOccurs="0"/> 
     <xs:element name="propertyValueMaxAmt" type="xs:decimal" minOccurs="0"/> 
    </xs:sequence> 
    </xs:complexType> 

    <xs:element name="calculateBorrowingDataResponse" type="tns:CalculateBorrowingDataResponseType"/> 
</xs:schema> 
Смежные вопросы