使用 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 对象,因为电话号码和地址是任意数量的。有什么想法吗?
最佳答案
众所周知,使用 JAXB 处理具有这些属性名称的 XML 结构非常困难。
因此,我建议使用更方便的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 就不会使用它们进行编码/解码。
最终实现一个私有(private)方法afterUnmarshal(Unmarshaller unmarshaller, Object parent)
您从 Map<QName, String>
中铲取内容的位置到List<String> addresses
和List<String> phoneNumbers
。
如 Unmarshal Event Callbacks 中所述
JAXB 将在适当的时候调用此方法。
如果你想写XML文件,你还需要一个私有(private)方法
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);
关于java - 将带有索引的属性列表转换为对象的 Xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46377769/