java - 将带有索引的属性列表转换为对象的 Xml

标签 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 对象,因为电话号码和地址是任意数量的。有什么想法吗?

最佳答案

众所周知,使用 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> addressesList<String> phoneNumbers 。 因此,您也声明了这些,但用 @XmlTransient 注释。 , 这样 JAXB 就不会使用它们进行编码/解码。

最终实现一个私有(private)方法afterUnmarshal(Unmarshaller unmarshaller, Object parent) 您从 Map<QName, String> 中铲取内容的位置到List<String> addressesList<String> phoneNumbers 。 如 Unmarshal Event Callbacks 中所述 JAXB 将在适当的时候调用此方法。

如果你想写XML文件,你还需要一个私有(private)方法 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);

关于java - 将带有索引的属性列表转换为对象的 Xml,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46377769/

相关文章:

java - Struts2: session 问题(反向代理后)

java - 尽管输入正确,但输入不正确

java - 在 Java 中将 Map 从 Class<?> 保存到 Handler 对象的最合适方法是什么?

java - 为什么我只有 Google Maps Android API V2 的空白 map ?

java - 不区分大小写 Jaxb2Marshaller

java - 使用 JAXB 的多个 XML 文件

java - 使用java.time.Instant来表示DateTime而不是OffsetDateTime

c# - 使用 Linq 和 XDocument,我可以获取父标签下的所有子元素吗?

Javascript XSLT 转换,将 XML 存储在变量中

java - XJC 不生成带有命名空间的@XmlElement 吗?