从MODS模式生成的JAXB不会获取元素的值

时间:2016-11-02 12:47:49

标签: java xml xsd jaxb xjc

我是在xsd(http://www.loc.gov/standards/mods/mods.xsd)的xjc类的帮助下生成的。现在我想读取元素的值,例如xml文件(https://www.loc.gov/standards/mods/v3/mods-userguide-examples.html - 第二个例子:Digitized Book)。我正在为这个返回列表或字符串(getter方法)的类动态获取类和方法。我得到的是属性值而不是元素值。

我的课程:解组

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 - 类型:null TitleInfo - 权限:null TitleInfo - ID:null TitleInfo - 脚本:null TitleInfo - ContentType:null TitleInfo - 角色:null TitleInfo - 用法:主要 TitleInfo - 标题:null TitleInfo - OtherType:null TitleInfo - 提供:是的 TitleInfo - 音译:null TitleInfo - NameTitleGroup:null TitleInfo - AltRepGroup:null TitleInfo - TypeBinded:简单 TitleInfo - AltFormat:null TitleInfo - DisplayLabel:null TitleInfo - Href:null TitleInfo - Arcrole:null TitleInfo - 显示:null TitleInfo - Actuate:null TitleInfo - Lang:null TitleInfo - LangBinded:null TitleInfo - AuthorityURI:null TitleInfo - ValueURI:null

生成的类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();

输出继电器: gov.loc.mods.v3.StringPlusLanguage@2986fc10

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

输出继电器: {http://www.loc.gov/mods/v3}标题

我如何获得title元素的价值?

1 个答案:

答案 0 :(得分:1)

当您获得java.lang.Exception: java.lang.NullPointerException at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462) at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:529) Caused by: java.lang.NullPointerException at CommutingTime1$Time_Ant10s.toString(CommutingTime1.java:179) at org.apache.hadoop.mapreduce.lib.output.TextOutputFormat$LineRecordWriter.writeObject(TextOutputFormat.java:85) at org.apache.hadoop.mapreduce.lib.output.TextOutputFormat$LineRecordWriter.write(TextOutputFormat.java:104) at org.apache.hadoop.mapred.ReduceTask$NewTrackingRecordWriter.write(ReduceTask.java:558) at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:89) at org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer$Context.write(WrappedReducer.java:105) at CommutingTime1$Reducer1.reduce(CommutingTime1.java:323) at CommutingTime1$Reducer1.reduce(CommutingTime1.java:291) at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:171) at org.apache.hadoop.mapred.ReduceTask.runNewReducer(ReduceTask.java:627) at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:389) at org.apache.hadoop.mapred.LocalJobRunner$Job$ReduceTaskRunnable.run(LocalJobRunner.java:319) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) 类实例时,它对应于您的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,则会获得字符串值属性。