gpt4 book ai didi

java - 从 XmlStreamReader 解码 JAXB 会导致 null 对象

转载 作者:行者123 更新时间:2023-11-30 02:35:56 24 4
gpt4 key购买 nike

我创建了一个用于解码 XML 消息的 Java 过程,其中可以提供“startTag”以在消息中的特定元素处开始解码。我用了XMLStreamReader进行此选择。

下面是我遇到的问题的完整复制粘贴演示。 “xml”消息是我需要处理的内容。不幸的是,它产生了 null结果中包含 car 对象,而“xmlStripped”消息则生成完全未编码的结果。

我将问题隔离到 xmlns="http://www.example.com/type" <response> 中的命名空间元素。当我删除它时,“xml”已正确解码。

无法控制 XML。 “xml”变量是我需要使用的变量。我对 XSD/ObjectFactory 的控制很少 ,所以我的第一个行动方针是在解码过程中寻找解决方案。

如果您知道失败的原因以及是否有解决方案,请告诉我。谢谢!

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

}

最佳答案

您可以通过创建 package-info.java 并添加以下内容来为您的模型设置 elementFormDefault="qualified":

package-info.java

@XmlSchema(namespace="http://www.example.com/type", elementFormDefault=XmlNsForm.QUALIFIED)

package mypkg;

import javax.xml.bind.annotation.*;

这将允许您的常规 XML 工作,但不允许您的“剥离”XML 工作。除了“剥离”外部包装元素之外,两者之间的区别在于原始 XML 具有默认命名空间集,而剥离的 XML 则没有。

关于java - 从 XmlStreamReader 解码 JAXB 会导致 null 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43071564/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com