Aby powiązać to, co inni już stwierdzili lub podpowiedzieli, zasady, według których JAXB XJC decyduje, czy umieścić @XmlRootElement
adnotację w wygenerowanej klasie, nie są trywialne ( zobacz ten artykuł ).
@XmlRootElement
istnieje, ponieważ środowisko wykonawcze JAXB wymaga pewnych informacji w celu uporządkowania / odmarszowania danego obiektu, w szczególności nazwy elementu XML i przestrzeni nazw. Nie możesz po prostu przekazać Marshallerowi żadnego starego obiektu. @XmlRootElement
zapewnia tę informację.
Adnotacja to jednak tylko wygoda - JAXB jej nie wymaga. Alternatywą jest użycie JAXBElement
obiektów opakowania, które dostarczają tych samych informacji co @XmlRootElement
, ale w formie obiektu, a nie adnotacji.
Jednak JAXBElement
obiekty są trudne do zbudowania, ponieważ musisz znać nazwę elementu XML i przestrzeń nazw, czego zwykle nie zna logika biznesowa.
Na szczęście, gdy XJC generuje model klasy, generuje również klasę o nazwie ObjectFactory
. Ma to częściowo na celu zapewnienie kompatybilności wstecznej z JAXB v1, ale jest także miejscem, w którym XJC może umieszczać wygenerowane metody fabryczne, które tworzą JAXBElement
opakowania wokół twoich obiektów. Obsługuje dla Ciebie nazwę XML i przestrzeń nazw, więc nie musisz się o to martwić. Wystarczy przejrzeć ObjectFactory
metody (w przypadku dużego schematu mogą istnieć setki), aby znaleźć tę, której potrzebujesz.
new ObjectFactory().createPositionReport(positionReport)
zwrotyJAXBElement<PositionReport>
JXBElement
? W moim przypadku metoda fabryczna to 0-arity i po prostu zwracanew
obiekt. (Dlaczego niektóre klasy otrzymują pomocników opakowania JAXBElement, a inne nie?) Chyba w takim przypadku musimy sami stworzyć opakowanie?Wspomniano o tym na dole wpisu na blogu, do którego link już powyżej, ale działa to jak dla mnie przyjemność:
źródło
jc
w powyższym fragmencie?Jak wskazano w jednej z powyższych odpowiedzi, nie otrzymasz XMLRootElement dla elementu głównego, jeśli w XSD jego typ jest zdefiniowany jako nazwany typ, ponieważ ten nazwany typ może być użyty gdzie indziej w twoim XSD. Spróbuj użyć tego typu anonimowego, tzn. Zamiast:
miałbyś:
źródło
@XmlRootElement nie jest potrzebny do odblokowania - jeśli używa się 2-parametrowej postaci Unmarshaller # unmarshall.
Więc jeśli zamiast robić:
należy zrobić:
Ten ostatni kod nie będzie wymagał adnotacji @XmlRootElement na poziomie klasy UserType.
źródło
String pathname = "file.xml"; InputStream stream = new FileInputStream(pathname); JAXBContext jaxbContext = JAXBContext.newInstance(UserType.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader someSource = factory.createXMLEventReader(stream); JAXBElement<UserType> userElement = jaxbUnmarshaller.unmarshal(someSource, UserType.class); UserType user = userElement.getValue();
Odpowiedź Joe (Joe 26 czerwca 09 o 17:26) robi to dla mnie. Prosta odpowiedź jest taka, że brak adnotacji @XmlRootElement nie stanowi problemu, jeśli utworzysz JAXBElement. Rzeczą, która mnie pomyliła, jest to, że ObjectFactory ma 2 metody createMyRootElement - pierwszy nie przyjmuje parametrów i daje rozpakowany obiekt, drugi bierze rozpakowany obiekt i zwraca go zawinięty w JAXBElement, a marshalling, że JAXBElement działa dobrze. Oto podstawowy kod, którego użyłem (jestem nowy, więc przepraszam, jeśli kod nie jest poprawnie sformatowany w tej odpowiedzi), w dużej mierze skopiowany z tekstu linku :
źródło
Możesz rozwiązać ten problem, używając powiązania z Jak wygenerować klasy @XmlRootElement dla typów podstawowych w XSD? .
Oto przykład z Maven
Oto
binding.xjb
treść plikuźródło
Jak wiadomo odpowiedzią jest użycie ObjectFactory (). Oto próbka kodu, który zadziałał dla mnie :)
źródło
To też nie działa dla nas. Ale znaleźliśmy szeroko cytowany artykuł, który dodaje NIEKTÓRE tło ... Link do niego tutaj ze względu na następną osobę: http://weblogs.java.net/blog/kohsuke/archive/2006/03 /why_does_jaxb_p.html
źródło
Po dwóch dniach przeszukiwania znalazłem rozwiązanie problemu. Możesz użyć klasy ObjectFactory do obejścia klas, które nie mają @XmlRootElement . ObjectFactory ma przeciążone metody, aby zawinąć ją wokół JAXBElement.
Metoda: 1 wykonuje proste utworzenie obiektu.
Metoda: 2 zawinie obiekt w @JAXBElement .
Zawsze używaj metody: 2, aby uniknąć wyjątku javax.xml.bind.MarshalException - z połączonym wyjątkiem brakuje adnotacji @XmlRootElement.
Poniżej znajduje się przykładowy kod
Metoda: 1 wykonuje proste utworzenie obiektu
Metoda: 2 zawinie obiekt w @JAXBElement .
Przykładowy kod roboczy:
źródło
Na wypadek, gdyby moje doświadczenie z tym problemem dało komuś Eurekę! moment .. Dodam następujące:
Ten problem również występował, gdy korzystałem z pliku xsd, który wygenerowałem przy pomocy opcji menu „Generuj xsd z dokumentu wystąpienia”.
Kiedy zaakceptowałem wszystkie domyślne ustawienia tego narzędzia, wygenerował on plik xsd, który przy użyciu z jaxb wygenerował pliki java bez
@XmlRootElement
. W czasie wykonywania, gdy próbowałem marszałka, dostałem ten sam wyjątek, co omówiony w tym pytaniu.Wróciłem do narzędzia IntellJ i zobaczyłem domyślną opcję w rozwijanym „Desgin Type” (czego oczywiście nie rozumiałem… i nadal nie rozumiem, jeśli jestem szczery):
Desgin Type:
Zmieniłem to na
, teraz wygenerował (zasadniczo) inny xsd, który wytworzył,
@XmlRootElement
gdy był używany z jaxb. Nie mogę powiedzieć, że rozumiem, co to jest, ale działało dla mnie.źródło
Za pomocą kompilacji Maven możesz dodać
@XmlRootElement
adnotacjęz
jaxb2-basics-annotate
wtyczką „ ”.Zobacz więcej informacji: patrz
Skonfiguruj Maven do generowania klas ze schematu XML przy użyciu JAXB
i generowanie kodu JAXB XJC
źródło
Opakowania JAXBElement działają w przypadkach, w których
@XmlRootElement
JAXB nie generuje żadnego . Te opakowania są dostępne wObjectFactory
klasie generowanej przezmaven-jaxb2-plugin
. Na przykład:źródło
Czy próbowałeś zmienić swój xsd w ten sposób?
źródło
Aby to rozwiązać, przed skonfigurowaniem kompilacji z programem wsimport należy skonfigurować powiązanie xml, ustawiając opcję replaceElementProperty na wartość false.
źródło
<jaxb:bindings> ... <jaxws:bindings> ... </jaxws:bindings> ... </jaxb:bindings>
Temat jest dość stary, ale nadal aktualny w kontekście biznesowym przedsiębiorstwa. Starałem się unikać dotykania xsds, aby łatwo je zaktualizować w przyszłości. Oto moje rozwiązania ..
1. Przeważnie
xjc:simple
wystarczaTworzy głównie XmlRootElements do importowania definicji xsd.
2. Podziel swoje
jaxb2-maven-plugin
egzekucjeSpotkałem się, że robi to ogromną różnicę, jeśli spróbujesz wygenerować klasy z wielu definicji xsd zamiast definicji wykonania dla xsd.
Więc jeśli masz definicję wielokrotności
<source>
, spróbuj po prostu podzielić je:Generator nie wychwytuje faktu, że jedna klasa może być wystarczająca, a zatem tworzy niestandardowe klasy dla każdego wykonania. I właśnie tego potrzebuję;).
źródło