JAXB - 如何使用Map中的属性创建XML元素?

时间:2015-08-10 13:17:01

标签: java xml jaxb xml-serialization

我需要这样的东西 -

<Token>
  <HighLevel info-1="" info-2=""/>
  <LowLevel>
    <LowLevel info-key="" info-value=""/>
    <LowLevel info-key="" info-value=""/>
          ....
  </LowLevel>
</Token >

我有Map for LowLevel元素,我希望像上面的XML一样填充其条目。 使用JAXB封装/绑定它的方法是什么?

1 个答案:

答案 0 :(得分:2)

您可以使用自定义适配器。实施例

//Token.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
class LowLevelToken {
    @XmlAttribute(name = "info-key")
    public String key;
    @XmlAttribute(name = "info-value")
    public String value;

    private LowLevelToken() {}

    public LowLevelToken(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

@XmlRootElement
class HighLevelToken {
    @XmlAttribute(name = "info-1")
    public String info1;
    @XmlAttribute(name = "info-2")
    public String info2;

    private HighLevelToken() {}

    public HighLevelToken(String info1, String info2) {
        this.info1 = info1;
        this.info2 = info2;
    }
}

class TokenWrapper {
    @XmlElement(name="LowLevel")
    public List<LowLevelToken> tokens = new ArrayList<LowLevelToken>();
}

class TokenAdapter extends XmlAdapter<TokenWrapper, Map<String, String>> {
    @Override
    public TokenWrapper marshal(Map<String, String> lowlevelTokens)
            throws Exception {
        TokenWrapper wrapper = new TokenWrapper();
        List<LowLevelToken> elements = new ArrayList<LowLevelToken>();
        for (Map.Entry<String, String> property : lowlevelTokens.entrySet()) {
            elements.add(new LowLevelToken(property.getKey(), property.getValue()));
        }
        wrapper.tokens = elements;
        return wrapper;
    }

    @Override
    public Map<String, String> unmarshal(TokenWrapper tokenWrapper) throws Exception {
        Map<String, String> tokens = null;
        if(tokenWrapper != null && tokenWrapper.tokens != null && !tokenWrapper.tokens.isEmpty()){
            tokens = new HashMap<String, String>();
            for(LowLevelToken token : tokenWrapper.tokens){
                tokens.put(token.key, token.value);
            }
        }
        return tokens;
    }
}

@XmlRootElement(name = "Token")
public class Token {

    HighLevelToken highLevel;
    Map<String, String> lowLevel;

    public HighLevelToken getHighLevel() {
        return highLevel;
    }

    @XmlElement(name = "HighLevel")
    public void setHighLevel(HighLevelToken highLevel) {
        this.highLevel = highLevel;
    }

    public Map<String, String> getLowLevel() {
        return lowLevel;
    }

    @XmlElement(name = "LowLevel")
    @XmlJavaTypeAdapter(TokenAdapter.class)
    public void setLowLevel(Map<String, String> lowLevel) {
        this.lowLevel = lowLevel;
    }
}

示例程序

import java.util.HashMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class JAXBExample {
    public static void main(String[] args) {
        Token token = new Token();
        token.setHighLevel(new HighLevelToken("1", "2"));
        token.setLowLevel(new HashMap<String, String>() {{ put("LK1", "LV1"); put("LK2", "LV2"); put("LK2", "LV2"); }});
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Token.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(token, System.out);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

这会生成

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Token>
    <HighLevel info-1="1" info-2="2"/>
    <LowLevel>
    <LowLevel info-key="LK2" info-value="LV2"/>
    <LowLevel info-key="LK1" info-value="LV1"/>
    </LowLevel>
</Token>