具有命名空间和前缀的 JAXB unmarshall

2022-09-02 23:51:41

我正在使用 JAXB 从 SOAP 响应中解析 xml 元素。我已经为xml元素定义了POJO类。我已经测试了没有命名空间的pojo类,并为其工作正常设置前缀。虽然当我尝试解析命名空间和前缀时,面对以下异常。要求是解析来自 SOAPMessage 对象的输入

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.xmlsoap.org/soap/envelope/", local:"Envelope"). Expected elements are <{}Envelope>

尝试通过在 package-info 中创建@XMLSchema来修复.java并将此文件放在 package 文件夹中。任何人都可以指导我前进吗?

推荐了这篇文章,但没有帮助我。

已编辑 :XMLSchema

@javax.xml.bind.annotation.XmlSchema (
    xmlns = {  @javax.xml.bind.annotation.XmlNs(prefix = "env", 
                 namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
      @javax.xml.bind.annotation.XmlNs(prefix="ns3", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
    }
  )
package com.one.two;

提前致谢


答案 1

这可以在不使用标准 SOAPMessage 类修改生成的 JAXB 代码的情况下完成。我在这里和这里写了这个

这有点麻烦,但工作正常。

编组

Farm farm = new Farm();
farm.getHorse().add(new Horse());
farm.getHorse().get(0).setName("glue factory");
farm.getHorse().get(0).setHeight(BigInteger.valueOf(123));

Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Marshaller marshaller = JAXBContext.newInstance(Farm.class).createMarshaller();
marshaller.marshal(farm, document);
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
soapMessage.getSOAPBody().addDocument(document);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
soapMessage.writeTo(outputStream);
String output = new String(outputStream.toByteArray());

解编组

String example =
        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header /><soapenv:Body><ns2:farm xmlns:ns2=\"http://adamish.com/example/farm\"><horse height=\"123\" name=\"glue factory\"/></ns2:farm></soapenv:Body></soapenv:Envelope>";
SOAPMessage message = MessageFactory.newInstance().createMessage(null,
        new ByteArrayInputStream(example.getBytes()));
Unmarshaller unmarshaller = JAXBContext.newInstance(Farm.class).createUnmarshaller();
Farm farm = (Farm)unmarshaller.unmarshal(message.getSOAPBody().extractContentAsDocument());

答案 2

以下是如何处理您的使用 cae:

如果需要映射元素Envelope

软件包信息

通常,您将按如下方式使用。像我所做的那样使用 and 属性意味着映射到 XML 元素的所有数据(除非另有映射)都将属于命名空间。中指定的信息用于 XML 模式生成,尽管某些 JAXB 实现在编组时使用它来确定命名空间的首选前缀(请参见:http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html)。@XmlSchemanamespaceelementFormDefaulthttp://www.xxxx.com/ncp/oomr/dto/xmlns

@XmlSchema (
    namespace="http://www.xxxx.com/ncp/oomr/dto/",
    elementFormDefault=XmlNsForm.QUALIFIED,
    xmlns = {  
        @XmlNs(prefix = "env", namespaceURI="http://schemas.xmlsoap.org/soap/envelope/"),
        @XmlNs(prefix="whatever", namespaceURI="http://www.xxxx.com/ncp/oomr/dto/")
    }
  )
package com.one.two;

import javax.xml.bind.annotation.*;

信封

如果在 中,您需要从命名空间映射到元素,则需要在 和 注释中指定它。com.one.twohttp://www.xxxx.com/ncp/oomr/dto/@XmlRootElement@XmlElement

package com.one.two;

import javax.xml.bind.annotation.*;

@XmlRootElement(name="Envelope", namespace="http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {

    @XmlElement(name="Body", namespace="http://schemas.xmlsoap.org/soap/envelope/")
    private Body body;

}

详细信息

如果你只是想映射身体

您可以使用 StAX 解析器来解析消息并前进到有效负载部分,然后从那里取消元组:

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;

public class UnmarshalDemo {

    public static void main(String[] args) throws Exception {
        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);
        xsr.nextTag();
        while(!xsr.getLocalName().equals("return")) {
            xsr.nextTag();
        }

        JAXBContext jc = JAXBContext.newInstance(Customer.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        JAXBElement<Customer> jb = unmarshaller.unmarshal(xsr, Customer.class);
        xsr.close();
    }

}

详细信息


推荐