使用Java(我目前正在使用jaxb2来解组xml文件),我可以解组看起来像这样的xml文件吗?
<person name="John" phoneNumber1="142125151" phoneNumber2="142124125151" phoneNumber3="142124125151"
address1="5 street" address2="35 street" address3="56-th and 3dh street"/>
这个想法是将具有这些属性(电话和地址)的Person对象作为字符串数组,因为电话号码和地址是任意数量。有什么想法吗?
答案 0 :(得分:1)
使用这些属性名称的XML结构很难用JAXB处理。
因此,我建议使用更方便的XML结构, 使用JAXB很容易处理:
<person name="John">
<phoneNumber>142125151</phoneNumber>
<phoneNumber>142124125151</phoneNumber>
<phoneNumber>142124125151</phoneNumber>
<address>5 street</address>
<address>35 street</address>
<address>56-th and 3dh street</address>
</person>
话虽如此,您可以处理原始的XML结构, 但付出了相当大的努力:
在Person
班级中,声明Map<QName, String>
注明了@XmlAnyAttribute
,
这样JAXB将使用它来编组/解组所有属性
(除了那些用@XmlAttribute
明确注释的那些)。
但您需要List<String> addresses
和List<String> phoneNumbers
。
因此你也声明了那些,但用@XmlTransient
注释,
这样JAXB就不会将它们用于编组/解组。
最后实现私有方法afterUnmarshal(Unmarshaller unmarshaller, Object parent)
在哪里铲起从Map<QName, String>
到List<String> addresses
的内容
和List<String> phoneNumbers
。
如Unmarshal Event Callbacks中所述
JAXB将在适当的时候调用此方法。
如果要编写XML文件,还需要私有方法
beforeMarshal(Marshaller marshaller)
你在哪里铲内容
从List<String> addresses
和List<String> phoneNumbers
返回Map<QName, String>
。
如Marshal Event Callbacks中所述
JAXB将在适当的时候调用此方法。
@XmlRootElement(name="person")
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
@XmlAttribute(name="name")
private String name;
@XmlAnyAttribute
private Map<QName, String> otherAttributes;
@XmlTransient // don't participate in marshalling/unmarhalling
private List<String> phoneNumbers;
@XmlTransient // don't participate in marshalling/unmarhalling
private List<String> addresses;
// add public getters/setters for name, addresses, phoneNumbers,
// but not for otherAttributes
@SuppressWarnings("unused") // called by JAXB
private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
addresses = new ArrayList<>();
phoneNumbers = new ArrayList<>();
for (QName qName : otherAttributes.keySet()) {
if (qName.getLocalPart().startsWith("address")) {
addresses.add(otherAttributes.get(qName));
}
if (qName.getLocalPart().startsWith("phoneNumber")) {
phoneNumbers.add(otherAttributes.get(qName));
}
}
}
@SuppressWarnings("unused") // called by JAXB
private boolean beforeMarshal(Marshaller marshaller) {
otherAttributes = new HashMap<>();
int i = 0;
for (String address : addresses) {
otherAttributes.put(new QName("address" + ++i), address);
}
i = 0;
for (String phoneNumber : phoneNumbers) {
otherAttributes.put(new QName("phoneNmber" + ++i), phoneNumber);
}
return true;
}
}
您可以使用此XML-Java-XML往返来测试上面的代码:
JAXBContext context = JAXBContext.newInstance(Person.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
File file = new File("person.xml");
Person person = (Person) unmarshaller.unmarshal(file);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(person, System.out);