具有索引的Xml转换属性列表到Object

时间:2017-09-23 08:47:49

标签: java xml jaxb

使用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对象作为字符串数组,因为电话号码和地址是任意数量。有什么想法吗?

1 个答案:

答案 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> addressesList<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> addressesList<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);