2016-11-02 5 views
0

Я сгенерировал с помощью классов xjc из xsd (http://www.loc.gov/standards/mods/mods.xsd). Теперь я хочу читать значения элементов, например, xml-файл (https://www.loc.gov/standards/mods/v3/mods-userguide-examples.html - второй пример: оцифрованная книга). Я динамически получаю классы и методы для этих классов, которые возвращают списки или строки (методы getter). Я получаю значения атрибутов, но не значения элементов.JAXB, созданный с помощью схемы MODS, не получает значений элементов

Мои классы: немаршалинг

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; 
    } 
} 

Класс для обработки данных XML

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!"); 
     } 
    } 
} 

Вывод атрибутов:

<mods version="3.3"> 

Mods - Версия: 3,3

Выхода для элементов:

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

TitleInfo - Тип: нулевой TitleInfo - Authority: нулевой TitleInfo - ID: нулевой TitleInfo - Скрипт: нулевой TitleInfo - ТипСодержимый: нулевой TitleInfo - Роль: нулевой TitleInfo - Использование: первичная TitleInfo - Название: нулевой TitleInfo - OtherType: нулевой TitleInfo - Поставляется: да TitleInfo - Транслитерация: нулевой TitleInfo - NameTitleGroup: нулевой TitleInfo - AltRepGroup: нулевой TitleInfo - TypeBinded: простой TitleInfo - AltFormat: нулевой TitleInfo - DisplayLabel: нулевой TitleInfo - HREF: нулевой TitleInfo - роль-дуги целевой: нулевой TitleInfo - Показать: нулевой TitleInfo - Активизировать: нулевой TitleInfo - Lang: нулевой TitleInfo - LangBinded: нулевой TitleInfo - AuthorityURI: нулевой TitleInfo - ValueURI: нулевой

Сгенерированный класс 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; 
    } 
    ....... 
} 

Я пытался получить это значение непосредственно:

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

Ouput: [email protected]

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

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

Как я могу получить значение элемента title?

ответ

1

Когда вы получите StringPlusLanguage экземпляр класса, соответствующий вашему элементу title.Это сложный тип с простым содержимым в схеме:

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

Таким образом, вы, вероятно, имеют свойство, как content или value, проверьте класс и доступ к этой недвижимости. Это будет содержать текстовое значение элемента.

Причина, по которой title не является просто строкой, является именно тем, что она смоделирована как сложный тип схемы. Если бы это было xs:string, вместо этого вы получили бы свойство строковых значений.