2016-01-05 6 views
0

Я полностью новичок в архитектуре JAXB. Но вот то, что я пытаюсь сделать, и где застрял в двух словах.JAXB, Unmarshalling и Marshalling против класса Wrapper.

Я создаю веб-приложение, в котором клиент сначала зарегистрирует свой xsd, а затем отправит свои данные xml/json в соответствии с xsd.

Для регистрации XSD, я использую XJC (не как Maven плагин, но вместо того, чтобы из самого кода Java:

SchemaCompiler sc = XJC.createSchemaCompiler(); 
    File schemaFile = new File(schemaPath); 
    InputSource is = new InputSource(new FileInputStream(schemaFile)); 
    is.setSystemId(schemaFile.getAbsolutePath()); 
    sc.parseSchema(is); 
    S2JJAXBModel model = sc.bind(); 
    JCodeModel jCodeModel = model.generateCode(null, null); 
    jCodeModel.build(new File(outputDirectory)); 

По XSD выглядит как:

<?xml version="1.0" encoding="UTF-8"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

    <xsd:element name="Metadata" type="Metadata" /> 

    <xsd:complexType name="Metadata"> 
     <xsd:sequence> 

      <xsd:element name="MicroscopeStagePosition" 
       type="MicroscopeStagePosition" maxOccurs="1" minOccurs="1"> 
      </xsd:element> 

     </xsd:sequence> 
    </xsd:complexType> 


    <xsd:complexType name="MicroscopeStagePosition"> 
     <xsd:sequence> 
      <xsd:element name="Start" type="xsd:string"/> 
      <xsd:element name="End" type="xsd:string"/> 
     </xsd:sequence> 
    </xsd:complexType> 
    </xsd:schema> 

Я создавая JAXB annoted классы POJO из вышеизложенного и 2 классов созданы являются:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "Metadata", propOrder = { 
    "microscopeStagePosition" 
}) 
public class Metadata { 

    @XmlElement(name = "MicroscopeStagePosition", required = true) 
    protected MicroscopeStagePosition microscopeStagePosition; 

    public MicroscopeStagePosition getMicroscopeStagePosition() { 
     return microscopeStagePosition; 
    } 
    public void setMicroscopeStagePosition(MicroscopeStagePosition value) { 
     this.microscopeStagePosition = value; 
    } 

} 

и

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "MicroscopeStagePosition", propOrder = { 
    "start", 
    "end" 
}) 
public class MicroscopeStagePosition { 

    @XmlElement(name = "Start", required = true) 
    protected String start; 
    @XmlElement(name = "End", required = true) 
    protected String end; 

    public String getStart() { 
     return start; 
    } 

    public void setStart(String value) { 
     this.start = value; 
    } 

    public String getEnd() { 
     return end; 
    } 

    public void setEnd(String value) { 
     this.end = value; 
    } 

} 

Теперь моя идея иметь общий аннотированный класс, который будет обертка вокруг этого выше классов, которые будут созданы в режиме реального времени (этот класс создается в реальном времени и, следовательно, может иметь все, что должно быть).

Проблема в том, что я не знаю, какой xsd придет и, следовательно, rootelement не поможет. Поэтому я думал создать оболочку вокруг созданного класса JAXB, а затем заниматься только этим оберточным классом во всем API.

я создал ниже класса в реальном времени:

public class MyModel { 
@XmlElement(required = true) 
protected Metadata Metadata; 
@XmlElement(required = true) 
protected MicroscopeStagePosition MicroscopeStagePosition; 
} 

Можно ли Unmarshell на входящий XML, основанный на этом классе обертке. Обратите внимание, что входящий XML не может быть принужден иметь в нем корневой элемент MyModel. Таким образом, я пытаюсь создать корневой JAXBElement, а затем присвоить его класса-оболочки:

MyModel je = new MyModel(); 

JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {MyModel.class}, null); 

     Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 

     InputStream is = new ByteArrayInputStream(sIncomingMetadataXML.getBytes()); 

     JAXBElement<MyModel> root = jaxbUnmarshaller.unmarshal(new StreamSource(
       is), MyModel.class); 
     je = root.getValue(); 

если я аннотирования MyModel с @XmlRootElement @XmlAccessorType (XmlAccessType.FIELD) и возвращения драг из моего апи его нулевой дочерний объект XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<MyModel/> 

и если не возникает ошибка:

сообщение тело писателя класса Java Aand MIME тип медиа приложения/XML не был найден.

Так может я создать класс-оболочку, как и выше, и если да, то как ?, или я пропустил совершенно что-то здесь

+0

Обратите внимание, что входящий XML не может быть принудительно иметь в нем корневой элемент MyModel. Почему бы и нет?, Кажется, самый простой способ. Храните встроенный xml (добавьте то, что вам нужно), а затем unmarshal, это вы можете сделать во время выполнения (без сохранения файла) .... –

+0

Хм, хорошо подумал, что это будет быть чистым кодом, но можете ли вы использовать elloborate, как добавить родительский тег к входящему XML без сохранения в файл? –

+0

Я отправил ответ, я делаю это часто, так как, когда я взаимодействую с другой службой (msxml ecc) из java, мне нужно обрабатывать разные заголовки спецификации ecc. Возможно, это занимает немного больше памяти, но у вас гораздо больше контроля над входящими данными ... –

ответ

0

Не считая «Обратите внимание на входящий XML не может быть принужден иметь корневой элемент MyModel в нем " как пользователь, одобренный в комментарии.

Вместо того, чтобы передавать поток непосредственно в Jaxb, вы читаете в StringBuffer. Это я часто занимаюсь обработкой разных заголовков UTF, регистрируя, как мне нравится, ecc.

В вашем случае, чтобы добавить отчаянно необходимый тег.

  1. Чтение поток в StringBuffer sb (см, как, например Read/convert an InputStream to a String)

  2. Вставка теги, как потребность в StringBuffer

  3. UnmarshallerStringBuffer

    StringReader reader = new StringReader(sb.toString()); 
    JAXBElement<MyModel> root = getUnmarshaller().unmarshal(reader) 
    
Смежные вопросы