java – JAXB解组树结构
发布时间:2020-12-15 02:09:28 所属栏目:Java 来源:网络整理
导读:我有 XML输入,它本质上是一个树结构.目标是(un)将代码编组到 Java类中. configkey-value-pair keyKey1/key valueValue1/value/key-value-pairkey-value-pair keyKey2/key value key-value-pair keySubkey2/key valueValue999/value /key-value-pair /value/k
我有
XML输入,它本质上是一个树结构.目标是(un)将代码编组到
Java类中.
<config> <key-value-pair> <key>Key1</key> <value>Value1</value> </key-value-pair> <key-value-pair> <key>Key2</key> <value> <key-value-pair> <key>Subkey2</key> <value>Value999</value> </key-value-pair> </value> </key-value-pair> </config> XML包含典型的键/值对.并且每个值可以包含另一个键/值对,或列表键/值对或仅包含单个字符串值. @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) static class KeyValuePair { @XmlElement(name="key") private String key; @XmlElement(name="value") private String value; // here I don't know how to reflect // the choice of String or another // list of KeyValuePair objects @XmlElement(name="value") private List<KeyValuePair> valuePairs; // getters/setters here } 然后我只有另一个包装类 @XmlRootElement(name="config") @XmlAccessorType(XmlAccessType.FIELD) static class Structure { @XmlElement(name="key-value-pair") private List<KeyValuePair> keyValuePair; // getters/setters } 这是我试图用于(联合国)编组的逻辑. Unmarshaller jaxbUnmarshaller = jc.createUnmarshaller(); StringReader reader = new StringReader(input); Structure struct = (Structure) jaxbUnmarshaller.unmarshal(reader); // struct doesn't get the data correctly ... 这是我到目前为止所得到的.它不像我拥有的??那样工作,但我希望我能清楚自己最终目标应该是什么样子. 我想在开始时使用XML并放入Structure类的实例. 解决方法
你可能已经想到了这个……
如果你开始在这样的模式级别建模它; <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="key-value-pair"> <xs:sequence> <xs:element name="key" type="xs:string"/> <xs:element name="value"> <xs:complexType mixed="true"> <xs:choice> <xs:element name="key-value-pair" type="key-value-pair" minOccurs="0"/> </xs:choice> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:element name="config"> <xs:complexType> <xs:sequence> <xs:element name="key-value-pair" type="key-value-pair" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> 然后使用XJC Ant Task或call it programmatically或其他任何内容来生成最终的JAXB类 package uk.co.his.test.model; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlMixed; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for key-value-pair complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="key-value-pair"> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element name="key" type="{http://www.w3.org/2001/XMLSchema}string"/> * <element name="value"> * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <choice> * <element name="key-value-pair" type="{}key-value-pair" minOccurs="0"/> * </choice> * </restriction> * </complexContent> * </complexType> * </element> * </sequence> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "key-value-pair",propOrder = { "key","value" }) public class KeyValuePair { @XmlElement(required = true) protected String key; @XmlElement(required = true) protected KeyValuePair.Value value; /** * Gets the value of the key property. * * @return * possible object is * {@link String } * */ public String getKey() { return key; } /** * Sets the value of the key property. * * @param value * allowed object is * {@link String } * */ public void setKey(String value) { this.key = value; } /** * Gets the value of the value property. * * @return * possible object is * {@link KeyValuePair.Value } * */ public KeyValuePair.Value getValue() { return value; } /** * Sets the value of the value property. * * @param value * allowed object is * {@link KeyValuePair.Value } * */ public void setValue(KeyValuePair.Value value) { this.value = value; } /** * <p>Java class for anonymous complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <choice> * <element name="key-value-pair" type="{}key-value-pair" minOccurs="0"/> * </choice> * </restriction> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "",propOrder = { "content" }) public static class Value { @XmlElementRef(name = "key-value-pair",type = JAXBElement.class,required = false) @XmlMixed protected List<Serializable> content; /** * Gets the value of the content property. * * <p> * This accessor method returns a reference to the live list,* not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. * This is why there is not a <CODE>set</CODE> method for the content property. * * <p> * For example,to add a new item,do as follows: * <pre> * getContent().add(newItem); * </pre> * * * <p> * Objects of the following type(s) are allowed in the list * {@link String } * {@link JAXBElement }{@code <}{@link KeyValuePair }{@code >} * * */ public List<Serializable> getContent() { if (content == null) { content = new ArrayList<Serializable>(); } return this.content; } } } 还有一个ObjectFactory和一个Config类(基本上就是你的Structure类). ObjectFactory给了我们一些’糖’来帮助可怕的JAXBElement舞蹈. 正如安德烈亚斯所说,仍将允许String和嵌套的KeyValuePair(s).然后,您必须使用验证器包装Config类以检查未发生的情况;例如; package uk.co.his.test; import java.io.Serializable; import java.util.List; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import uk.co.his.test.model.Config; import uk.co.his.test.model.KeyValuePair; public class Validate { public void validate(Config c) throws JAXBException { for(KeyValuePair kvp: c.getKeyValuePair()) { validate(kvp); } } public void validate(KeyValuePair kv) throws JAXBException { List<Serializable> mixed = kv.getValue().getContent(); boolean nonWhitespaceStringFound = false; boolean kvpFound = false; for(Serializable c: mixed) { if(c instanceof String) { String s = (String) c; if(s.trim().length()>0) { nonWhitespaceStringFound = true; } } else { @SuppressWarnings("unchecked") JAXBElement<KeyValuePair> t = (JAXBElement<KeyValuePair>) c; KeyValuePair child = t.getValue(); kvpFound = true; validate(child); } if(kvpFound && nonWhitespaceStringFound) { throw new JAXBException("KeyValuePair "+kv.getKey()+" value element contained String data and nested KeyValuePair(s)"); } } } } 要创建配置,您必须进行JAXBElement舞蹈; private static final File Test1Out = new File("files/test1.xml"); @Test public void test1() throws JAXBException { ObjectFactory of = new ObjectFactory(); Config c = new Config(); c.getKeyValuePair().add(createKVPair(of,2,"a","one")); c.getKeyValuePair().add(createKVPair(of,1,"b","two")); c.getKeyValuePair().add(createKVPair(of,"c","three")); JAXBContext jbc = JAXBContext.newInstance("uk.co.his.test.model"); Marshaller m = jbc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE); m.marshal(c,Test1Out); Unmarshaller u = jbc.createUnmarshaller(); Config c2 = (Config) u.unmarshal(Test1Out); Assert.assertTrue("Round trip produces different things",c2.getKeyValuePair().size() ==3); } private KeyValuePair createKVPair(ObjectFactory of,int depth,int length,String initialKey,String value) { KeyValuePair kv = new KeyValuePair(); kv.setKey(initialKey); Value v = new Value(); kv.setValue(v); if(depth==0) { v.getContent().add(value); } else { int newdepth = --depth; for(int i = 0; i < length; i++) { v.getContent().add(of.createKeyValuePairValueKeyValuePair(createKVPair(of,newdepth,length,initialKey+depth,value+i))); } } return kv; } 嗯,这是一个开始…… (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |