如何删除SOAPHeaderElement的命名空间

时间:2017-08-14 16:46:29

标签: java xml jaxb

我有一个Java类来生成以下XML

<v:Envelope xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
    <v:Header>
        <b>LGE Nexus 5</b>
        <c>ANDROID</c>
        <d>6.0.1</d>
        <e>4.1.5</e>
        <f>127.0.0.1</f>
        <g/>?<g>
        <h>0.0</h>
        <i>0.0</i>
        <j"/>
        <k>8320738e-8634-4f73-a4dd-874a5d79e336</k>
        <l>2017-08-14 13:24:01</l>
        <m>8797e74f0d6eb7b1ff3dc114d4aa12d3</m>
    </v:Header>
    <v:Body>
        <ns2:getStatus xmlns:ns2="http://soap.ws.placa.service.sinesp.serpro.gov.br/">
            <a>ABC1234</a>
        </ns2:getStatus>
    </v:Body>
</v:Envelope>

但我目前的结果是:

<v:Envelope xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
    <v:Header>
        <b xmlns="http://schemas.xmlsoap.org/soap/envelope/">LGE Nexus 5</b>
        <c xmlns="http://schemas.xmlsoap.org/soap/envelope/">ANDROID</c>
        <d xmlns="http://schemas.xmlsoap.org/soap/envelope/">6.0.1</d>
        <e xmlns="http://schemas.xmlsoap.org/soap/envelope/">4.1.5</e>
        <f xmlns="http://schemas.xmlsoap.org/soap/envelope/">127.0.0.1</f>
        <g xmlns="http://schemas.xmlsoap.org/soap/envelope/">?</g>
        <h xmlns="http://schemas.xmlsoap.org/soap/envelope/">0.0</h>
        <i xmlns="http://schemas.xmlsoap.org/soap/envelope/">0.0</i>
        <j xmlns="http://schemas.xmlsoap.org/soap/envelope/" />
        <k xmlns="http://schemas.xmlsoap.org/soap/envelope/">8320738e-8634-4f73-a4dd-874a5d79e336</k>
        <l xmlns="http://schemas.xmlsoap.org/soap/envelope/">2017-08-14 13:24:01</l>
        <m xmlns="http://schemas.xmlsoap.org/soap/envelope/">8797e74f0d6eb7b1ff3dc114d4aa12d3</m>
    </v:Header>
    <v:Body>
        <ns2:getStatus xmlns:ns2="http://soap.ws.placa.service.sinesp.serpro.gov.br/">
            <a>ABC1234</a>
        </ns2:getStatus>
    </v:Body>
</v:Envelope>

我的class如下:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import org.w3c.dom.Document;

@XmlRootElement(name = "getStatus", namespace = "http://soap.ws.placa.service.sinesp.serpro.gov.br/")
public class Request {

  private String plate;

  private String device;
  private Double latitude;
  private String operationalSystem;
  private String majorVersion;
  private String minorVersion;
  private String ip;
  private String token;
  private String uuid;
  private Double longitude;
  private String date;
  private String hash;

  public Request() {
    this.device = "LGE Nexus 5";
    this.operationalSystem = "ANDROID";
    this.majorVersion = "6.0.1";
    this.minorVersion = "4.1.5";
    this.ip = "127.0.0.1";
    this.hash = "8797e74f0d6eb7b1ff3dc114d4aa12d3";
  }

  @XmlElement(name = "a")
  public String getPlate() {
    return plate;
  }

  public void setPlate(String plate) {
    this.plate = plate;
  }

  @XmlTransient
  public String getDevice() {
    return device;
  }

  public void setDevice(String device) {
    this.device = device;
  }

  @XmlTransient
  public Double getLatitude() {
    return latitude;
  }

  public void setLatitude(Double latitude) {
    this.latitude = latitude;
  }

  @XmlTransient
  public String getOperationalSystem() {
    return operationalSystem;
  }

  public void setOperationalSystem(String operationalSystem) {
    this.operationalSystem = operationalSystem;
  }

  @XmlTransient
  public String getMajorVersion() {
    return majorVersion;
  }

  public void setMajorVersion(String majorVersion) {
    this.majorVersion = majorVersion;
  }

  @XmlTransient
  public String getMinorVersion() {
    return minorVersion;
  }

  public void setMinorVersion(String minorVersion) {
    this.minorVersion = minorVersion;
  }

  @XmlTransient
  public String getIp() {
    return ip;
  }

  public void setIp(String ip) {
    this.ip = ip;
  }

  @XmlTransient
  public String getToken() {
    return token;
  }

  public void setToken(String token) {
    this.token = token;
  }

  @XmlTransient
  public String getUuid() {
    return uuid;
  }

  public void setUuid(String uuid) {
    this.uuid = uuid;
  }

  @XmlTransient
  public Double getLongitude() {
    return longitude;
  }

  public void setLongitude(Double longitude) {
    this.longitude = longitude;
  }

  @XmlTransient
  public String getDate() {
    return date;
  }

  public void setDate(String date) {
    this.date = date;
  }

  @XmlTransient
  public String getHash() {
    return hash;
  }

  public void setHash(String hash) {
    this.hash = hash;
  }

  public String toXML() {
    Document document;
    Marshaller marshaller;
    SOAPMessage soapMessage;
    ByteArrayOutputStream outputStream;
    String output;

    try {
      document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
      marshaller = JAXBContext.newInstance(Request.class).createMarshaller();
      marshaller.marshal(this, document);
      soapMessage = MessageFactory.newInstance().createMessage();
      this.fillEnvelope(soapMessage.getSOAPPart().getEnvelope());
      this.fillBody(soapMessage.getSOAPBody(), document);
      this.fillHeaders(soapMessage.getSOAPHeader());
      outputStream = new ByteArrayOutputStream();
      soapMessage.writeTo(outputStream);
      output = new String(outputStream.toByteArray());
    } catch (IOException | JAXBException | ParserConfigurationException | SOAPException ex) {
      throw new RuntimeException(ex);
    }

    return output;
  }

  private void fillEnvelope(SOAPEnvelope envelope) {
    Iterator prefixes;
    envelope.setPrefix("v");

    prefixes = envelope.getNamespacePrefixes();

    while (prefixes.hasNext()) {
      String prefix = (String) prefixes.next();

      envelope.removeNamespaceDeclaration(prefix);
    }
  }

  private void fillHeaders(SOAPHeader soapHeader) throws SOAPException {
    soapHeader.setPrefix("v");

    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "b")).setValue(this.device);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "c")).setValue(this.operationalSystem);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "d")).setValue(this.majorVersion);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "e")).setValue(this.minorVersion);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "f")).setValue(this.ip);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "g")).setValue(this.token);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "h")).setValue(String.valueOf(this.longitude));
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "i")).setValue(String.valueOf(this.latitude));
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "j")).setValue("");
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "k")).setValue(this.uuid);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "l")).setValue(this.date);
    soapHeader.addHeaderElement(new QName(soapHeader.getNamespaceURI(), "m")).setValue(this.hash);
  }

  private void fillBody(SOAPBody soapBody, Document document) throws SOAPException {
    soapBody.addDocument(document);
    soapBody.setPrefix("v");
  }
}

测试方法是:

public static void main(String[] args) {
  Request request = new Request();

  request.setToken("?");
  request.setLatitude(0.0);
  request.setLongitude(0.0);
  request.setUuid(UUID.randomUUID().toString()); // RFC 4122 Class 4 random UUID    
  request.setDate("2017-08-14 13:24:01");
  request.setPlate("ABC1234");

  System.out.println(request.toXML());
}

我需要做些什么才能删除namespace的{​​{1}}属性?

3 个答案:

答案 0 :(得分:2)

您可以使用正则表达式删除命名空间:

xml.replaceAll(" xmlns=\".*?\"", "");

其中变量xml是您的XML字符串。

答案 1 :(得分:1)

每个SOAP标头块(Header元素的直接子节点)必须根据SOAP specification限定名称空间。因此,您的XML将违反SOAP规范。

您当然可以使用其他方法或纯XML库来创建所需的XML,但在使用soapHeader.addHeaderElement时,JAX-RS实现(至少在Oracle的JRE中)验证此要求并抛出异常,如果您尝试添加带有空名称的标题块。

答案 2 :(得分:0)

这是一个对我有用的恶心黑客。首先,您需要知道 namespaceURI 存储在哪个类中。您可以通过调试应用程序、查看 SOAPHeaderElement 对象的字段并导航到 namespaceURI 的源来实现这一点。

从那里,您在实例化后使用反射将字段设置为空。然后删除该属性。这应该导致属性不被写出。这取决于实现。

SOAPHeaderElement headerElement = header.addHeaderElement(new QName("whatever", "myHeaderName") );
// Disgusting hack to remove the xmlns attribute
Field namespaceURIField = ElementNSImpl.class.getDeclaredField("namespaceURI");
namespaceURIField.setAccessible(true);
namespaceURIField.set(headerElement, null);
namespaceURIField.setAccessible(false);
headerElement.removeAttribute("xmlns");