使用 JAXB 实现具有属性和内容的 XML 元素

如何使用 JAXB 生成以下 XML?

<sport type="" gender="">
sport description
</sport>
151077 次浏览

Updated Solution - using the schema solution that we were debating. This gets you to your answer:

Sample Schema:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/Sport"
xmlns:tns="http://www.example.org/Sport"
elementFormDefault="qualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">


<complexType name="sportType">
<attribute name="type" type="string" />
<attribute name="gender" type="string" />
</complexType>


<element name="sports">
<complexType>
<sequence>
<element name="sport" minOccurs="0" maxOccurs="unbounded"
type="tns:sportType" />
</sequence>
</complexType>
</element>

Code Generated

SportType:

package org.example.sport;


import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;




@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sportType")
public class SportType {


@XmlAttribute
protected String type;
@XmlAttribute
protected String gender;


public String getType() {
return type;
}




public void setType(String value) {
this.type = value;
}


public String getGender() {
return gender;
}


public void setGender(String value) {
this.gender = value;
}


}

Sports:

package org.example.sport;


import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;




@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"sport"
})
@XmlRootElement(name = "sports")
public class Sports {


protected List<SportType> sport;


public List<SportType> getSport() {
if (sport == null) {
sport = new ArrayList<SportType>();
}
return this.sport;
}


}

Output class files are produced by running xjc against the schema on the command line

Annotate type and gender properties with @XmlAttribute and the description property with @XmlValue:

package org.example.sport;


import javax.xml.bind.annotation.*;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
public class Sport {


@XmlAttribute
protected String type;


@XmlAttribute
protected String gender;


@XmlValue;
protected String description;


}

For More Information

The correct scheme should be:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/Sport"
xmlns:tns="http://www.example.org/Sport"
elementFormDefault="qualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">


<complexType name="sportType">
<simpleContent>
<extension base="string">
<attribute name="type" type="string" />
<attribute name="gender" type="string" />
</extension>
</simpleContent>
</complexType>


<element name="sports">
<complexType>
<sequence>
<element name="sport" minOccurs="0" maxOccurs="unbounded"
type="tns:sportType" />
</sequence>
</complexType>
</element>

Code generated for SportType will be:

package org.example.sport;


import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;




@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "sportType")
public class SportType {
@XmlValue
protected String value;
@XmlAttribute
protected String type;
@XmlAttribute
protected String gender;


public String getValue() {
return value;
}


public void setValue(String value) {
this.value = value;
}


public String getType() {
return type;
}




public void setType(String value) {
this.type = value;
}


public String getGender() {
return gender;
}


public void setGender(String value) {
this.gender = value;
}
}

Here is working solution:

Output:

public class XmlTest {


private static final Logger log = LoggerFactory.getLogger(XmlTest.class);


@Test
public void createDefaultBook() throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
Marshaller marshaller = jaxbContext.createMarshaller();


StringWriter writer = new StringWriter();
marshaller.marshal(new Book(), writer);


log.debug("Book xml:\n {}", writer.toString());
}




@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "book")
public static class Book {


@XmlElementRef(name = "price")
private Price price = new Price();




}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "price")
public static class Price {
@XmlAttribute(name = "drawable")
private Boolean drawable = true; //you may want to set default value here


@XmlValue
private int priceValue = 1234;


public Boolean getDrawable() {
return drawable;
}


public void setDrawable(Boolean drawable) {
this.drawable = drawable;
}


public int getPriceValue() {
return priceValue;
}


public void setPriceValue(int priceValue) {
this.priceValue = priceValue;
}
}
}

Output:

22:00:18.471 [main] DEBUG com.grebski.stack.XmlTest - Book xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book>
<price drawable="true">1234</price>
</book>