2016-05-23 38 views
5

Jest sprzedawca dostarczone XML tak:JAXB i mniej przestrzeni nazw XML

<?xml version="1.0" encoding="utf-8"?> 
<Foo> 
    <Bar>...</Bar> 
    <Bar>...</Bar> 
</Foo> 

Uwaga nie ma deklaracji xmlns="...", ani sprzedawca dostarczy schematu. Nie można tego zmienić, a dostawca będzie nadal wysyłał XML w ten sposób w przyszłości.

Aby wygenerować powiązania JAXB, I utworzeniu schematu tak:

<?xml version="1.0" encoding="utf-8"?> 
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="http://acme.com/schema" 
      xmlns:tns="http://acme.com/schema" 
      elementFormDefault="qualified"> 
    <xsd:element name="Foo"> 
     <xsd:complexType> 
      <xsd:sequence> 
       <xsd:element ref="tns:Bar" maxOccurs="unbounded"/> 
      </xsd:sequence> 
     </xsd:complexType> 
    </xsd:element> 
    <xsd:element name="Bar"> 
     ... 
    </xsd:element> 
</xsd:schema> 

Zauważ, że mam deklarowaną mniej lub bardziej sensowne nazw („http://acme.com/schema”), tak, że może on być stosowany do elementu referencje, itp XJC generuje następujące package-info.java:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://acme.com/schema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package com.acme.schema; 

Wtedy staram się unmarshal dokumentu XML:

JAXBContext jaxb = JAXBContext.newInstance("com.acme.schema"); 
Unmarshaller unmarshaller = jaxb.createUnmarshaller(); 
InputStream is = this.getClass().getClassLoader().getResourceAsStream("test.xml"); 

InputSource source = new InputSource(is); 
Foo foo = (Foo) unmarshaller.unmarshal(source); 

Oto wyjątek uzyskać:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Foo"). Expected elements are <{http://acme.com/schema}Foo>,...> 

Oczywiście dzieje się tak dlatego, że elementy XML należą do pustej przestrzeni nazw, podczas gdy klasy JAXB ma niepusty jeden.

Czy istnieje sposób na sfałszowanie przestrzeni nazw XML (prawdopodobnie podczas analizy XML), aby JAXB rozpoznał elementy i skutecznie je powiązał? Rozwiązania SAX/StAX byłyby lepsze od DOM, ponieważ dokumenty XML mogłyby być raczej ogromne.

+0

czy mogłabyś umieścić klas generowanych przez XJC na? –

Odpowiedz

2

Po pierwsze, nie polecam tego wszystkiego. Integracja z zewnętrznym API jest dość skomplikowana, bez dodatkowych komplikacji. Po co w ogóle dodawać przestrzeni nazw? Nie jestem pewien, co z tego wyniknie. Pomyśl o szczęśliwej osobie, która odziedziczy bazę kodu. Zobaczą dodawanie przestrzeni nazw, ale nie mają pojęcia, dlaczego to robisz.

Chciałbym pójść o krok dalej i zasugerować całkowite unikanie schematu i stosowanie tylko dodanych adnotacji POJO. Wszystkie te kroki po prostu dodają komplikacji, budują kroki, itp.

Jednakże, jeśli jesteś zdeterminowany, wydaje się to być kluczowym przypadkiem transformacji XSL. Można znaleźć XSL przekształcać, który dodaje nazw dość łatwo, jak this question to jest to prosta sprawa okablowania swoją transformację do JAXB ...

private static Foo unmarshalDocument(InputStream xslStream, InputStream xmlStream) throws Exception { 
    StreamSource stylesource = new StreamSource(xslStream); 
    StreamSource inputStream = new StreamSource(xmlStream); 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource); 
    JAXBResult result = new JAXBResult(context); 
    transformer.transform(inputStream, result); 
    return (Foo) result.getResult(); 
} 
+0

Rzeczywiście okazało się, że przestrzeń nazw w ogóle nie była potrzebna. (Dalsze czytanie: O'Reilly "Schemat XML", rozdział 10, "Kontrolowanie przestrzeni nazw"). Nukleardowałem przedrostki 'targetNamespace =', 'xmlns: tns =' i 'tns:', a problem został rozwiązany z dala. –

+0

Jeśli chodzi o XJC vs. POJO - pokazałem tylko fragment kodu XML, prawdziwe dokumenty są znacznie bardziej złożone; ręczne wytwarzanie adnotacji POJO byłoby tutaj przesadą. Zamiast tego użyliśmy doskonałego projektanta schematów z narzędzi NetBeans XML, zastosowanych minimalnych dostosowań JAXB i voilà. To był oszczędny czas. Jeśli chodzi o proces budowania, to jest napędzany przez Maven + [maven-jaxb2-plugin] (https://github.com/highsource/maven-jaxb2-plugin), więc cała złożoność jest ukryta. Pamiętam jednak sytuacje, w których klasy generowane przez XJC wymagały znacznego ręcznego dostosowania, więc idea regeneracji została odrzucona. –