2016-11-02 3 views
0

Ich habe mit Hilfe von xjc Klassen aus xsd (http://www.loc.gov/standards/mods/mods.xsd) generiert. Jetzt möchte ich Werte von Elementen zum Beispiel XML-Datei lesen (https://www.loc.gov/standards/mods/v3/mods-userguide-examples.html - zweites Beispiel: digitalisiertes Buch). Ich bekomme dynamisch Klassen und Methoden für diese Klassen, die Listen oder Strings (Getter-Methoden) zurückgeben. Ich bekomme Werte von Attributen, aber keine Werte von Elementen.JAXB generiert von MODS Schema erhält keine Werte von Elementen

Meine Klassen: Unmarshalling

import java.io.File; 
import java.util.List; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Unmarshaller; 

public class XMLToObject { 

    /** 
    * 
    * @return List of mods definitions from xml file 
    */ 
    public static List convert() { 
     try { 
      JAXBContext jaxbContext = JAXBContext.newInstance(ModsCollectionDefinition.class); 
      Unmarshaller u = jaxbContext.createUnmarshaller(); 

      File f = new File("test.xml"); 
      ModsCollectionDefinition test = (ModsCollectionDefinition)((javax.xml.bind.JAXBElement) u.unmarshal(f)).getValue(); 
      return test.getMods(); 
     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 

Klasse für Daten XML-Verarbeitung

import java.lang.reflect.*; 
import java.util.List; 
import org.example.mods.XMLToObject; 
/** 
* Operations on XML data 
*/ 
public class MODS { 
    private static List xmlData = XMLToObject.convert(); 
    public static StringBuilder stringBuilder = new StringBuilder(); 

    /** 
    * 
    * Get the whole content of the xml file 
    * 
    * @return String 
    */ 
    public String getXML() { 
     if(xmlData != null) { 
      processClass(xmlData); 
      xmlData = null; 
     } else { 
      stringBuilder.append("No file imported!"); 
     } 
     return stringBuilder.toString(); 
    } 

    /** 
    * 
    * @param list from which will be derived class type 
    */ 
    private void processClass(List list) { 
     for (int i = 0; i < list.size(); i++) { 
      Class current = castDynamic(list.get(i)); 
      try { 
       Method[] methods = current.getMethods(); 
       if (methods.length > 0) { 
        for (int j = 0; j < methods.length; j++) { 
         if (checkIfMethodReturnsString(methods[j]) && !methods[j].getName().contains("toString")) { 
          callMethodWhichReturnsString(methods[j], list.get(i)); 
         } else if (checkIfMethodReturnsList(methods[j])) { 
          callMethodWhichReturnsList(methods[j], list.get(i)); 
         } 
        } 
       } 
      } catch (NullPointerException e) { 
       stringBuilder.append("No methods in this class!"); 
      } 
     } 
    } 

    /** 
    * 
    * @param object from which will be derived class 
    * @return Class 
    */ 
    private Class castDynamic(Object object) { 
     String className = object.getClass().getName(); 
     try { 
      Class cls = Class.forName(className); 
      cls.cast(object); 
      return cls; 
     } catch (ClassNotFoundException e) { 
      return null; 
     } 
    } 

    /** 
    * 
    * @param method of the class 
    * @return String 
    */ 
    private String getMethodType(Method method) { 
     return method.getReturnType().getName(); 
    } 

    /** 
    * 
    * @param method which will be checked according to return type 
    * @return boolean 
    */ 
    private boolean checkIfMethodReturnsString(Method method) { 
     if(getMethodType(method).contains("String")) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    /** 
    * 
    * @param method which will be checked according to return type 
    * @return boolean 
    */ 
    private boolean checkIfMethodReturnsList(Method method) { 
     if(getMethodType(method).contains("List")) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    /** 
    * 
    * 
    * @param method which is invoked 
    * @param obj on which method is invoked 
    */ 
    private void callMethodWhichReturnsList(Method method, Object obj) { 
     try { 
      List list = (List) method.invoke(obj); 
      processClass(list); 
     } catch (IllegalAccessException | InvocationTargetException ex) { 
      stringBuilder.append("Invoke exception!"); 
     } 
    } 

    /** 
    * Method returns strings which are attributes but doesn't return values of the elements! 
    * 
    * @param method which is invoked 
    * @param obj on which method is invoked 
    */ 
    private void callMethodWhichReturnsString(Method method, Object obj) { 
     try { 
      stringBuilder.append(obj.getClass().getSimpleName().replace("Definition", "")); 
      stringBuilder.append(" - "); 
      stringBuilder.append(method.getName().replace("get", "")); 
      stringBuilder.append(": "); 
      stringBuilder.append(method.invoke(obj)); 
     } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ex) { 
      stringBuilder.append("Invoke exception!"); 
     } 
    } 
} 

Ausgang für Attribute:

<mods version="3.3"> 

Mods - Version: 3,3

Ausgang für Elemente:

<titleInfo> 
    <title>At Gettysburg, or, What a Girl Saw and Heard of the Battle: A True Narrative</title> 
</titleInfo> 

titleinfo - Typ: null titleinfo - Behörde: null titleinfo - ID: null titleinfo - Script: null titleinfo - Content: null titleinfo - Rolle: null titleinfo - Verbrauch: primäre titleinfo - Titel: null titleinfo - OTHER: null titleinfo - Lieferung: ja titleinfo - Trans: null titleinfo - NameTitleGroup: null titleinfo - AltRepGroup: null titleinfo - TypeBinded: simple titleinfo - AltFormat: null titleinfo - Displaylabel: null titleinfo - Href: null titleinfo - arcrole: null titleinfo - Anzeigen: null titleinfo - Actuate: null titleinfo - Lang: null titleinfo - LangBinded: null titleinfo - AuthorityURI: null titleinfo - ValueURI: null

generiert Klasse TitleInfoDefinition:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "titleInfoDefinition", propOrder = { 
    "titleOrSubTitleOrPartNumber" 
}) 
public class TitleInfoDefinition { 

    @XmlElementRefs({ 
     ....... 
     @XmlElementRef(name = "title", namespace = "http://www.loc.gov/mods/v3", type = JAXBElement.class, required = false), 
     ...... 
    }) 
    protected List<Object> titleOrSubTitleOrPartNumber; 
    ...... 
    @XmlAttribute(name = "title", namespace = "http://www.w3.org/1999/xlink") 
    protected String title; 
    ..... 

    * <p> 
    * Objects of the following type(s) are allowed in the list 
    * {@link JAXBElement }{@code <}{@link StringPlusLanguage }{@code >} 
    * {@link JAXBElement }{@code <}{@link StringPlusLanguage }{@code >} 
    * {@link JAXBElement }{@code <}{@link StringPlusLanguage }{@code >} 
    * {@link JAXBElement }{@code <}{@link StringPlusLanguage }{@code >} 
    * {@link NonSort } 
    * 
    * 
    */ 
    public List<Object> getTitleOrSubTitleOrPartNumber() { 
     if (titleOrSubTitleOrPartNumber == null) { 
      titleOrSubTitleOrPartNumber = new ArrayList<Object>(); 
     } 
     return this.titleOrSubTitleOrPartNumber; 
    } 

    ...... 

    /** 
    * Ruft den Wert der title-Eigenschaft ab. 
    * 
    * @return 
    *  possible object is 
    *  {@link String } 
    *  
    */ 
    public String getTitle() { 
     return title; 
    } 
    ....... 
} 

Ich habe versucht, direkt mit diesen Wert zu erhalten:

((JAXBElement)((TitleInfoDefinition)test).getTitleOrSubTitleOrPartNumber().get(0)).getValue(); 

Ouput: [email protected]

((JAXBElement)((TitleInfoDefinition)test).getTitleOrSubTitleOrPartNumber().get(0)).getName() 

Ouput: { http://www.loc.gov/mods/v3} Titel

Wie kann ich Wert von Titelelement bekommen?

Antwort

1

Wenn Sie die Klasseninstanz StringPlusLanguage erhalten, entspricht dies Ihrem Element title.Dies ist ein komplexer Typ mit einfachen Inhalt in dem Schema:

<xs:complexType name="stringPlusLanguage"> 
    <xs:simpleContent> 
     <xs:extension base="xs:string"> 
      <xs:attributeGroup ref="languageAttributeGroup"/> 
     </xs:extension> 
    </xs:simpleContent> 
</xs:complexType> 

So haben Sie wahrscheinlich eine Eigenschaft wie content oder value, die Klasse überprüfen und diese Eigenschaft zugreifen. Dies enthält den Textwert des Elements.

Der Grund, dass title nicht nur Zeichenfolge ist, ist genau, weil es als ein komplexer Typ im Schema modelliert wird. Wenn es stattdessen xs:string gewesen wäre, würden Sie stattdessen eine String-Werte-Eigenschaft erhalten.

Verwandte Themen