Null 防止使用JAXB从XSD生成空@XmlType注释

Null 防止使用JAXB从XSD生成空@XmlType注释,null,jaxb,unmarshalling,xmlstreamreader,Null,Jaxb,Unmarshalling,Xmlstreamreader,让我从我的问题归结为什么开始。我正在使用maven-jaxb2-plugin从XSD模式生成一个名为MyServiceResponse的类。生成的MyServiceResponse类包含带有空名称属性的@XmlType注释 @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { }) 我想使用填充的name属性生成MyServiceResponse,或者不使用@XmlType注释。这是否

让我从我的问题归结为什么开始。我正在使用maven-jaxb2-plugin从XSD模式生成一个名为MyServiceResponse的类。生成的MyServiceResponse类包含带有空名称属性的
@XmlType
注释

 @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {

    })
我想使用填充的
name
属性生成MyServiceResponse,或者不使用
@XmlType
注释。这是否可以在XJB文件中使用自定义绑定或以其他方式实现?无论如何,如果可能的话,我想在生成过程中解决这个问题,因为每次运行Maven插件时,对MyserviceResponse的手动编辑都会被覆盖

下面是一个Java类,它演示了我的实际问题。该类使用XmlStreamReader和JAXB从消息中的任何元素开始解组XML消息。“xml”变量未完全解组。“car”属性保持为空。发生这种情况的原因是
xmlns=”http://www.example.com/type
命名空间由XmlStreamReader复制到Body元素,但不复制到Car子元素。不知何故,JAXB无法看到我希望它继续对Car元素进行解组。(这里有个大问号)

我已经知道一些修复,但它们涉及到对XSD或MyServiceResponse类的手动更改

首先,我可以在XSD上设置
elementFormDefault=“qualified”
,从中生成MyServiceResponse类、ObjectFactory和一个package-info.java。这是可行的,但它也会导致我的请求XML消息使用限定的名称空间进行封送,而我将消息发送到的服务不接受这一点。此外,它还需要对XSD进行更改,如果可能的话,我宁愿避免这样做

其次,在Body和Car@XmlType注释上设置名称起作用:
@XmlType(name=“Body”,propOrder={})
@XmlType(name=“Car”,propOrder={})
。但它需要手动编辑MyServiceResponse

第三个,删除
@XmlType(name=”,propOrder={})
注释是可行的,但它还涉及到手动编辑MyServiceResponse

这是一个可复制的演示类:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.Reader;
import java.io.StringReader;

public class XmlStreamReaderUnmarshallingTest {

    private static JAXBContext jaxbContext;

    static {
        try {
            jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    private static String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<soapenv:Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n" +
            "\txmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" \n" +
            "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
            "\t<soapenv:Body>\n" +
            "\t\t<response xmlns=\"http://www.example.com/type\">\n" +
            "\t\t\t<type:serviceResponse xmlns:type=\"http://www.example.com/type\">\n" +
            "\t\t\t\t<Body>\n" +
            "\t\t\t\t\t<Car>\n" +
            "\t\t\t\t\t\t<Brand>Mitsubishi</Brand>\n" +
            "\t\t\t\t\t\t<Color>Red</Color>\n" +
            "\t\t\t\t\t</Car>\n" +
            "\t\t\t\t</Body>\n" +
            "\t\t\t</type:serviceResponse>\n" +
            "\t\t</response>\n" +
            "\t</soapenv:Body>\n" +
            "</soapenv:Envelope>";


    private static String xmlStripped = "<type:serviceResponse xmlns:type=\"http://www.example.com/type\">\n" +
            "\t\t\t\t<Body>\n" +
            "\t\t\t\t\t<Car>\n" +
            "\t\t\t\t\t\t<Brand>Mitsubishi</Brand>\n" +
            "\t\t\t\t\t\t<Color>Red</Color>\n" +
            "\t\t\t\t\t</Car>\n" +
            "\t\t\t\t</Body>\n" +
            "\t\t\t</type:serviceResponse>";


    public static void main(String[] args) throws JAXBException, XMLStreamException {
        readXml(xml, "serviceResponse");
        readXml(xmlStripped, "serviceResponse");
    }

    private static void readXml(String inputXml, String startFromElement) throws JAXBException, XMLStreamException {

        final XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
        final Reader reader = new StringReader(inputXml);
        final XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(reader);
        final XMLStreamReader streamReader = skipToElement(xmlStreamReader, startFromElement);
        final MyServiceResponse serviceResponse = (MyServiceResponse) unmarshal(streamReader);

        if(serviceResponse.getBody().getCar() == null) {
            System.out.println("It didn't work :-(");
        } else {
            System.out.println("It worked");
        }
    }

    private static XMLStreamReader skipToElement(final XMLStreamReader xsr, final String startAtElement) throws XMLStreamException {
        while (startAtElement != null && xsr.hasNext()) {
            xsr.next();
            if (xsr.hasName()) {
                final String name = xsr.getName().getLocalPart();
                if (name.equals(startAtElement)) {
                    return xsr;
                }
            }
        }

        throw new IllegalArgumentException(String.format("Could not find element %s in response", startAtElement));
    }

    private static Object unmarshal(final XMLStreamReader xsr) throws JAXBException {
        final Object entity = unmarshaller(jaxbContext).unmarshal(xsr);
        return (entity instanceof JAXBElement ? ((JAXBElement) entity).getValue() : entity);
    }

    // Create unmarshaller every time
    private static Unmarshaller unmarshaller(JAXBContext context) throws JAXBException {

        return context.createUnmarshaller();

    }
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyServiceResponse", propOrder = {

})
class MyServiceResponse {

    @XmlElement(name = "Body")
    protected MyServiceResponse.Body body;

    /**
     * Gets the value of the body property.
     *
     * @return
     *     possible object is
     *     {@link MyServiceResponse.Body }
     *
     */
    public MyServiceResponse.Body getBody() {
        return body;
    }

    /**
     * Sets the value of the body property.
     *
     * @param value
     *     allowed object is
     *     {@link MyServiceResponse.Body }
     *
     */
    public void setBody(MyServiceResponse.Body value) {
        this.body = value;
    }


    /**
     * <p>Java class for anonymous complex type.
     *
     * <p>The following schema fragment specifies the expected content contained within this class.
     *
     * <pre>
     * &lt;complexType&gt;
     *   &lt;complexContent&gt;
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
     *       &lt;all&gt;
     *         &lt;element name="Car" minOccurs="0"&gt;
     *           &lt;complexType&gt;
     *             &lt;complexContent&gt;
     *               &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
     *                 &lt;all&gt;
     *                   &lt;element name="Brand" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
     *                   &lt;element name="Color" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
     *                 &lt;/all&gt;
     *               &lt;/restriction&gt;
     *             &lt;/complexContent&gt;
     *           &lt;/complexType&gt;
     *         &lt;/element&gt;
     *       &lt;/all&gt;
     *     &lt;/restriction&gt;
     *   &lt;/complexContent&gt;
     * &lt;/complexType&gt;
     * </pre>
     *
     *
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {

    })
    public static class Body {

        @XmlElement(name = "Car")
        protected MyServiceResponse.Body.Car car;

        /**
         * Gets the value of the car property.
         *
         * @return
         *     possible object is
         *     {@link MyServiceResponse.Body.Car }
         *
         */
        public MyServiceResponse.Body.Car getCar() {
            return car;
        }

        /**
         * Sets the value of the car property.
         *
         * @param value
         *     allowed object is
         *     {@link MyServiceResponse.Body.Car }
         *
         */
        public void setCar(MyServiceResponse.Body.Car value) {
            this.car = value;
        }


        /**
         * <p>Java class for anonymous complex type.
         *
         * <p>The following schema fragment specifies the expected content contained within this class.
         *
         * <pre>
         * &lt;complexType&gt;
         *   &lt;complexContent&gt;
         *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
         *       &lt;all&gt;
         *         &lt;element name="Brand" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
         *         &lt;element name="Color" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/&gt;
         *       &lt;/all&gt;
         *     &lt;/restriction&gt;
         *   &lt;/complexContent&gt;
         * &lt;/complexType&gt;
         * </pre>
         *
         *
         */
        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {

        })
        public static class Car {

            @XmlElement(name = "Brand")
            protected String brand;
            @XmlElement(name = "Color")
            protected String color;

            /**
             * Gets the value of the brand property.
             *
             * @return
             *     possible object is
             *     {@link String }
             *
             */
            public String getBrand() {
                return brand;
            }

            /**
             * Sets the value of the brand property.
             *
             * @param value
             *     allowed object is
             *     {@link String }
             *
             */
            public void setBrand(String value) {
                this.brand = value;
            }

            /**
             * Gets the value of the color property.
             *
             * @return
             *     possible object is
             *     {@link String }
             *
             */
            public String getColor() {
                return color;
            }

            /**
             * Sets the value of the color property.
             *
             * @param value
             *     allowed object is
             *     {@link String }
             *
             */
            public void setColor(String value) {
                this.color = value;
            }

        }

    }

}


@XmlRegistry
class ObjectFactory {

    private final static QName _ServiceResponse_QNAME = new QName("http://www.example.com/type", "serviceResponse");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.example.type
     *
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link MyServiceResponse }
     *
     */
    public MyServiceResponse createMyServiceResponse() {
        return new MyServiceResponse();
    }

    /**
     * Create an instance of {@link MyServiceResponse.Body }
     *
     */
    public MyServiceResponse.Body createMyServiceResponseBody() {
        return new MyServiceResponse.Body();
    }

    /**
     * Create an instance of {@link MyServiceResponse.Body.Car }
     *
     */
    public MyServiceResponse.Body.Car createMyServiceResponseBodyCar() {
        return new MyServiceResponse.Body.Car();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link MyServiceResponse }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "http://www.example.com/type", name = "serviceResponse")
    public JAXBElement<MyServiceResponse> createServiceResponse(MyServiceResponse value) {
        return new JAXBElement<MyServiceResponse>(_ServiceResponse_QNAME, MyServiceResponse.class, null, value);
    }

}
import javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBElement;
导入javax.xml.bind.JAXBException;
导入javax.xml.bind.Unmarshaller;
导入javax.xml.bind.annotation.*;
导入javax.xml.namespace.QName;
导入javax.xml.stream.XMLInputFactory;
导入javax.xml.stream.XMLStreamException;
导入javax.xml.stream.XMLStreamReader;
导入java.io.Reader;
导入java.io.StringReader;
公共类XmlStreamReaderUnmarshallingTest{
私有静态JAXBContext JAXBContext;
静止的{
试一试{
jaxbContext=jaxbContext.newInstance(ObjectFactory.class);
}捕获(JAXBEException e){
e、 printStackTrace();
}
}
私有静态字符串xml=“\n”+
“\n”+
“\t\n”+
“\t\t\n”+
“\t\t\t\n”+
“\t\t\t\t\n”+
“\t\t\t\t\t\n”+
“\t\t\t\t\t\tMitsubishi\n”+
“\t\t\t\t\t\t\tRed\n”+
“\t\t\t\t\t\n”+
“\t\t\t\t\n”+
“\t\t\t\n”+
“\t\t\n”+
“\t\n”+
"";
私有静态字符串xmlStripped=“\n”+
“\t\t\t\t\n”+
“\t\t\t\t\t\n”+
“\t\t\t\t\t\tMitsubishi\n”+
“\t\t\t\t\t\t\tRed\n”+
“\t\t\t\t\t\n”+
“\t\t\t\t\n”+
“\t\t\t”;
公共静态void main(字符串[]args)抛出JAXBEException、XMLStreamException{
readXml(xml,“服务响应”);
readXml(xmlStripped,“serviceResponse”);
}
私有静态void readXml(String inputXml,String startFromElement)抛出JAXBEException,XMLStreamException{
最终XMLInputFactory XMLInputFactory=XMLInputFactory.newFactory();
最终读取器=新的StringReader(inputXml);
最终XMLStreamReader=xmlInputFactory.createXMLStreamReader(读取器);
最终XMLStreamReader streamReader=skipToElement(XMLStreamReader,startFromElement);
最终MyServiceResponse serviceResponse=(MyServiceResponse)解组(streamReader);
如果(serviceResponse.getBody().getCar()==null){
System.out.println(“它不工作:-(”);
}否则{
System.out.println(“它成功了”);
}
}
私有静态XMLStreamReader skipToElement(最终XMLStreamReader xsr,最终字符串StartElement)抛出XMLStreamException{
while(startAtElement!=null&&xsr.hasNext()){
xsr.next();
if(xsr.hasName()){
最终字符串名称=xsr.getName().getLocalPart();
if(name.equals(startElement)){
返回xsr;
}
}
}
抛出新的IllegalArgumentException(String.format(“在响应中找不到元素%s”,StartElement));
}
私有静态对象解组(最终XMLStreamReader xsr)抛出JAXBEException{
最终对象实体=unmarshaller(jaxbContext).unmarshal(xsr);
返回(实体instanceof JAXBElement?((JAXBElement)entity).getValue():entity);
}
//每次创建解组器
私有静态解组器解组器(JAXBContext上下文)抛出JAXBEException{
返回context.createUnmarshaller();
}
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name=“MyServiceResponse”,proporter={
})
类MyServiceResponse{
@xmlement(name=“Body”)
保护我的服务响应。身体;
/**
*获取body属性的值。
*
*@返回
*可能的对象是
*{@link MyServiceResponse.Body}
*
*/
public-myservicesponse.Body-getBody(){
返回体;
}
/**
*
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/type"
           targetNamespace="http://www.example.com/type" elementFormDefault="qualified" >
    <xs:element name="serviceResponse" type="MyServiceResponse"/>
    <xs:complexType name="MyServiceResponse">
        <xs:all>
            <xs:element name="Body" minOccurs="0">
                <xs:complexType>
                    <xs:all>
                        <xs:element name="Car" minOccurs="0">
                            <xs:complexType>
                                <xs:all>
                                    <xs:element name="Brand" type="xs:string" minOccurs="0"/>
                                    <xs:element name="Color" type="xs:string" minOccurs="0"/>
                                </xs:all>
                            </xs:complexType>
                        </xs:element>
                    </xs:all>
                </xs:complexType>
            </xs:element>
        </xs:all>
    </xs:complexType>
</xs:schema>
<type:serviceResponse xmlns:type="http://www.example.com/type"> 
    <Body xmlns="http://www.example.com/type"> 
        <Car> 
            <Brand>Mitsubishi</Brand> 
            <Color>Red</Color> 
        </Car> 
    </Body> 
</type:serviceResponse>
<xs:element name="Body" type="Body" minOccurs="0" />
<xs:complexType name="Body"> 
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.com/type"
    targetNamespace="http://www.example.com/type" elementFormDefault="unqualified" >

    <xs:element name="serviceResponse" type="MyServiceResponse"/>

    <xs:complexType name="MyServiceResponse">
        <xs:all>
            <xs:element name="Body" type="Body" minOccurs="0" />
        </xs:all>
    </xs:complexType>
    <xs:complexType name="Body">
        <xs:all>
            <xs:element name="Car" type="Car" minOccurs="0"/>
        </xs:all>
    </xs:complexType>
    <xs:complexType name="Car">
        <xs:all>
            <xs:element name="Brand" type="xs:string" minOccurs="0"/>
            <xs:element name="Color" type="xs:string" minOccurs="0"/>
        </xs:all>
    </xs:complexType>    
</xs:schema>