Elemento XML con atributo y contenido usando JAXB

78

¿Cómo puedo generar el siguiente XML usando JAXB?

<sport type="" gender="">
    sport description
</sport>
James
fuente

Respuestas:

130

Anote las propiedades de tipo y género con @XmlAttributey la propiedad de descripción con @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;

}

Para más información

bdoughan
fuente
10

El esquema correcto debería ser:

<?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>

El código generado para SportType será:

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;
    }
}
niega
fuente
8

Aquí está la solución de trabajo:

Salida:

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;
        }
    }
}

Salida:

22: 00: 18.471 [principal] DEBUG com.grebski.stack.XmlTest - Libro xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book>
    <price drawable="true">1234</price>
</book>
rgrebski
fuente
Solo quería agregar un enlace a una respuesta similar para ayudar a quienes vean esto como una solución. Buena respuesta, por cierto. stackoverflow.com/a/15429363/1686575
John Manko
me salvas ! : DI resuelto con la utilización de @XmlValue
Angelo
4

Solución actualizada: utilizando la solución de esquema que estábamos debatiendo. Esto te lleva a tu respuesta:

Esquema de muestra:

<?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>

Código generado

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;
    }

}

Deportes:

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;
    }

}

Los archivos de clase de salida se producen ejecutando xjc contra el esquema en la línea de comando

Jim
fuente
1
No usa XSD. Usando anotaciones JAXB.
James
Claro, pero puede producir un XSD muy simple para describir la estructura XML anterior para generar archivos de código Java para usted con las anotaciones. Alternativamente, puede crearlos manualmente, la estructura de anotaciones debe estar en los documentos. La ventaja de usar un XSD es que es muy rápido cambiar la estructura y regenerar los archivos de código Java. Depende de lo cómodo que se sienta con cualquiera de los enfoques download.oracle.com/javaee/5/tutorial/doc/bnbah.html
Jim
1
Gracias por su respuesta. Pero mi problema es cómo generar XML dado usando anotaciones manualmente. ¿Cómo necesito definir mis archivos de clase de entidad?
James
Vea mi nueva solución arriba, realmente espero que esto ayude
Jim