Mam do czynienia z problemem rozrządowym/niemagającym, obejmującym dziedziczenie i polimorfizm za pomocą implementacji MOXy JAXB i zewnętrznego pliku powiązań metadanych.eclipselink/Moxy: przepełnienie dziedziczenia i nazwy atrybutu oparte na typie
Nie kontroluję plików XML ani klas modeli.
W modelu istnieje wiele klas dziedziczących inne klasy DTO. . Oto przykład środowiska pracuję w tym przykładzie jest tylko tutaj w jakimś celu składni, prawdziwe środowisko obejmuje zagnieżdżony dziedziczenia, kolekcje itp:
Oto klasy, które będą dziedziczone
class A {
private String name;
public String getName(){
return name;
}
public void setName(String value){
name = value;
}
}
Oto jeden dziedziczone klasy
class B extends A {
private String attrFromB;
public String getAttrFromB(){
return attrFromB;
}
public void setAttrFromB(String value){
attrFromB = value;
}
}
I jeszcze
class C extends A {
private String attrFromC;
public String getAttrFromC(){
return attrFromC;
}
public void setAttrFromC(String value){
attrFromC= value;
}
}
Oto klasa pojemnik
class MyContainerClass{
private A myObject;
public A getMyObject(){
return myObject;
}
public void setMyObject(A value){
myObject = value;
}
}
Oto XML, który powinien produkować w przypadku MyContainer zawierających
<MyContainer>
<MyObject nameA="foo" />
</MyContainer>
MyContainer zawierający b
<MyContainer>
<MyObject nameB="foo" attrFromB="bar" />
</MyContainer>
And MyContainer zawierający C
<MyContainer>
<MyObject nameC="foo" attrFromC="bar" />
</MyContainer>
Więc widać już problemy w horyzoncie ...
Tutaj jest plik mapowania, że chciałbym napisać:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="com.test.example"
version="2.1">
<java-type name="A" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameA" />
</java-attributes>
</java-type>
<java-type name="B" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<xml-see-also>
com.test.example.A
</xml.see.also>
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameB" />
<xml-element java-attribute="attrFromB" xml-path="@attrFromB" />
</java-attributes>
</java-type>
<java-type name="C" xml-accessor-type="NONE">
<xml-root-element name="MyObject" />
<xml-see-also>
com.test.example.A
</xml.see.also>
<java-attributes>
<xml-element java-attribute="name" xml-path="@nameC" />
<xml-element java-attribute="attrFromC" xml-path="@attrFromC" />
</java-attributes>
</java-type>
<java-type name="MyContainer" xml-accessor-type="NONE">
<xml-root-element name="MyContainer" />
<java-attributes>
<xml-element java-attribute="myObject" type="com.test.example.A" xml-path="MyObject" />
</java-attributes>
</java-type>
</xml-bindings>
Pierwszym problemem jest to, że jeśli wiążę klas jak że pojawia się następujący wyjątek:
[Exception [EclipseLink-44] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class indicator field from database row [UnmarshalRecord()].
1st pytanie: rozumiem, że to jest normalne , Jaxb potrzebuje jakiegoś sposobu, aby określić typ atrybutu MyContaioner.myObject. Problem polega na tym, że nie mam dostępu do przychodzących plików XML, więc nie mogę dodawać do nich pól xsi: type. Czy istnieje sposób określania klasy na podstawie obecności w niej określonego atrybutu? niezależnie od jego wartości. Jeśli xml źródłowy zawiera atrybut @attrFromC, wiem, że obiekt powinien być typu C. Jeśli zawiera attrFromB, to B.
Drugim problemem jest to, że „nazwa” atrybut nie istnieje wewnątrz B i C, więc jaxb ignoruje je.
--Ignoring attribute [name] on class [com.test.example.B] as no Property was generated for it.
--Ignoring attribute [name] on class [com.test.example.C] as no Property was generated for it.
2-te pytanie: Innym problemem jest to, że nie wiem, czy jest w stanie JAXB nadrzędnymi xml nazw atrybutów jak oczekuje się wewnątrz pliku XML (@nameA, @nameB i nameC wszystkim odnosząc się do A. imię), czy jest jakiś sposób na zrobienie tego?
Z góry dziękuję za poświęcony czas.
Czytając pierwszą część swojej odpowiedzi, to już jest naprawdę pomocne. Dzięki. Nie mogę się doczekać drugiej części. – Drewman
Dla pewności, jeśli w klasie Extractor, chcę przetestować obecność węzła, a nie atrybut. Czy mogę użyć record.get ("SomeNodeName") lub record.get ("SomeNodeName/text()")? – Drewman
@ user1121108 - Dodałem odpowiedź dla drugiej części. W ekstraktorze klasowym będziesz mógł testować tylko obecność atrybutów. W tym momencie wykonania elementy podrzędne nie zostały jeszcze przetworzone. –