一:需求
下面是给定的xml格式,需要用javax.xml.bind.annotation 来映射成对象,给别的类调用。从中需要解析出Item 的文本值,每个Item的 code,Cost,charge,OrderNo ,Count的值。
<Exam>
<ExamItem>
<Item code='001' Cost='123.45' Charge='123.45' OrderNo='123456' Count='1'>脊椎检查项目</Item>
<Item code='002' Cost='153.00' Charge='123.45' OrderNo='123457' Count='1'>肺部检查项目</Item>
</ExamItem>
</Exam>
二:解决办法
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "Exam")
public class ReqEaxmsInfo {
@XmlElement(name = "ExamItem")
private ExamItem examItem;
@XmlAccessorType(XmlAccessType.NONE)
public static class ExamItem {
@XmlElement(name = "Item")
private List<Item> item;
public List<Item> getItem() {
return item;
}
public void setItem(List<Item> item) {
this.item = item;
}
}
@XmlRootElement(name="Item")
@XmlAccessorType(XmlAccessType.NONE)
public static class Item{
@XmlAnyAttribute()
private Map code;//每个Item的属性值
@XmlValue
private String text;
public Map getCode() {
return code;
}
public void setCode(Map code) {
this.code = code;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
public ExamItem getExamItem() {
return examItem;
}
public void setExamItem(ExamItem examItem) {
this.examItem = examItem;
}
}
这里多设计一个Item类对应xml里面的<Item>节点,里面(Map)code 被@XmlAnyAttribute()注解标识。
@XmlAnyAttribute()这个注解官方给出解释比较笼统:将 JavaBean 属性映射到通配符属性的映射表中
反正没看懂,但是它的使用条件给了我很大启发:
最多只能使用 @XmlAnyAttribute 注释类中的一个字段或属性。
属性或字段的类型必须是 java.util.Map。
思考了一下,如要要取得 code,Cost,charge,OrderNo ,Count的值,也要将这些放入一个Map里面去,才比较好取值。所以尝试了一下并且成功了。
(String)text 字段被@XmlValue 注解标识,@XmlValue用来获取节点的值。也就是<Item></Item>中的值。
问题:取不到Map里面的值
当我这样信心满满的搞定的时候,在获取值得问题上被卡住了。我一度以为jdk有毛病...........
ReqEaxmsInfo examsInfo = (ReqEaxmsInfo) marshallerUtils.parseXmlDataObject(ReqEaxmsInfo.class, examsXml);
Map map= examsInfo.getExamItem().getItem().get(0).getCode();
System.out.println("Map----->"+map);
System.out.println("Map keySet()------->"+map.keySet());
System.out.println("code---->"+map.get("code"));
结果却是:
Map----->{Cost=123.45, Count=1, OrderNo=123456, Charge=123.45, code=001}
Map keySet()------->[Cost, Count, OrderNo, Charge, code]
code---->null
我的内心是崩溃的,应为明明Map里面有值,却用Map.get("code") 取不到。嗯,当时我想肯定jdk有问题(玩笑话)。
解决:QName类型的key
Map里面有值,却取不到,肯定就是key不对,要么写错了,要么类型不多。排除第一个,那就是类型不对,不是String类型的,那是什么类型???又开始翻文档。
在处理将解组成为一个值类的属性时,与另一个 JavaBean 属性不存在静态关联的(通过 XmlAttribute)每个属性都被输入 Map<QName,Object> 表示的通配符属性映射表中。属性 QName 是映射表的键。键值是属性的字符串值。
嗯,没错,key的类型是QName类型的,妈蛋,啥玩意不知道,欺负新人.........再去翻文档
static QName valueOf(String qNameAsString)
从解析格式化 String 中派生的 QName。
呃,一大串文字也没看太懂,反正一眼就看到这个。然后然后就搞定鸟。
System.out.println(map.get(QName.valueOf("code")));
用valueOf这个方法将字符串转成QName,再把它当作key去取值,就可以顺利取出来了