从 MODS 模式生成的 JAXB 不获取元素的值
JAXB generated from MODS schema doesn't get values of elements
我在 xjc 的帮助下从 xsd 中生成了 classes(http://www.loc.gov/standards/mods/mods.xsd). Now I want to read values of elements for example xml file (https://www.loc.gov/standards/mods/v3/mods-userguide-examples.html - 第二个示例:数字化书籍)。我正在动态获取 classes 和此 classes 的方法,其中 returns 列出或字符串(getter 方法)。我得到的是属性值而不是元素值。
我的 classes:解组
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;
}
}
Class 用于处理 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">
模组 - 版本:3.3
元素的输出:
<titleInfo>
<title>At Gettysburg, or, What a Girl Saw and Heard of the Battle: A True Narrative</title>
</titleInfo>
TitleInfo - 类型:空
TitleInfo - 权限:null
TitleInfo - ID:空
TitleInfo - 脚本:空
TitleInfo - ContentType:空
TitleInfo - 角色:空
TitleInfo - 用法:主要
TitleInfo - 标题:空
TitleInfo - 其他类型:空
TitleInfo - 提供:是
TitleInfo - 音译:空
TitleInfo - NameTitleGroup:空
TitleInfo - AltRepGroup:空
TitleInfo - TypeBinded:简单
TitleInfo - AltFormat:空
标题信息 - 显示标签:空
TitleInfo - Href:空
TitleInfo - Arcrole: 空
TitleInfo - 显示:空
TitleInfo - 启动:空
TitleInfo - 语言:空
TitleInfo - LangBinded: 空
TitleInfo - AuthorityURI: 空
TitleInfo - ValueURI: null
已生成 class 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 元素的值?
当您获得 StringPlusLanguage
class 实例时,它对应于您的 title
元素。这是一个复杂的类型,架构中的内容很简单:
<xs:complexType name="stringPlusLanguage">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attributeGroup ref="languageAttributeGroup"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
所以您可能有一个 属性,例如 content
或 value
,检查 class 并访问此 属性。这将包含元素的文本值。
title
不只是字符串的原因恰恰是因为它在模式中被建模为复杂类型。如果它本来是 xs:string
,那么你会得到一个字符串值 属性。
我在 xjc 的帮助下从 xsd 中生成了 classes(http://www.loc.gov/standards/mods/mods.xsd). Now I want to read values of elements for example xml file (https://www.loc.gov/standards/mods/v3/mods-userguide-examples.html - 第二个示例:数字化书籍)。我正在动态获取 classes 和此 classes 的方法,其中 returns 列出或字符串(getter 方法)。我得到的是属性值而不是元素值。
我的 classes:解组
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;
}
}
Class 用于处理 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">
模组 - 版本:3.3
元素的输出:
<titleInfo>
<title>At Gettysburg, or, What a Girl Saw and Heard of the Battle: A True Narrative</title>
</titleInfo>
TitleInfo - 类型:空 TitleInfo - 权限:null TitleInfo - ID:空 TitleInfo - 脚本:空 TitleInfo - ContentType:空 TitleInfo - 角色:空 TitleInfo - 用法:主要 TitleInfo - 标题:空 TitleInfo - 其他类型:空 TitleInfo - 提供:是 TitleInfo - 音译:空 TitleInfo - NameTitleGroup:空 TitleInfo - AltRepGroup:空 TitleInfo - TypeBinded:简单 TitleInfo - AltFormat:空 标题信息 - 显示标签:空 TitleInfo - Href:空 TitleInfo - Arcrole: 空 TitleInfo - 显示:空 TitleInfo - 启动:空 TitleInfo - 语言:空 TitleInfo - LangBinded: 空 TitleInfo - AuthorityURI: 空 TitleInfo - ValueURI: null
已生成 class 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 元素的值?
当您获得 StringPlusLanguage
class 实例时,它对应于您的 title
元素。这是一个复杂的类型,架构中的内容很简单:
<xs:complexType name="stringPlusLanguage">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attributeGroup ref="languageAttributeGroup"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
所以您可能有一个 属性,例如 content
或 value
,检查 class 并访问此 属性。这将包含元素的文本值。
title
不只是字符串的原因恰恰是因为它在模式中被建模为复杂类型。如果它本来是 xs:string
,那么你会得到一个字符串值 属性。