Document to String y viceversa

	public static String documentToString(Document doc) {
		return sourceToString(new DOMSource(doc));
	}
	
	public static String sourceToString(Source source) {
		try {
			StringWriter sw = new StringWriter();
			TransformerFactory tf = TransformerFactory.newInstance();
			Transformer transformer = tf.newTransformer();
			transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

			transformer.transform(source, new StreamResult(sw));
			return sw.toString();
		} catch (Exception ex) {
			throw new RuntimeException("Error converting to String", ex);
		}
	}
	
	public static Source toSource(String xml){
		return new StreamSource(new StringReader(xml));
	}
	
	public static Document stringToDocument(String xml) {
		Document doc = null;
		try {
			DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			doc = db.parse( new InputSource( new StringReader( xml ) ) ); 
		} catch (Exception e) {
			throw new RuntimeException("Error converting to String", e);
		}
		return doc;
	}
	
	public static Source stringToDocumentToSource(String xml) {
		return new DOMSource(stringToDocument(xml));
	}
	
	public static Source stringToSource(String xml) {
		return new StreamSource(new StringReader(xml));
	}

¿Porque es importante el Source?. A la hora de realizar el marshall/unmarshall de objetos y strings JAXB siempre quiere datos de tipo Source.

	public Object xmlToObject(String xml) throws Exception {
		ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(getEncoding()));
		StreamSource source = new StreamSource(bais);
		return xmlToObject(source);
	}
	
	public Object xmlToObject(Source source) throws Exception {
		return jaxb2Marshaller.unmarshal(source);
	}
Document to String y viceversa

javax.xml.soap.DetailEntry to xml

He encontrado documentacion de como crear los mensajes SoapFaul con el detalle como si fuese un XML. Pero ninguno que indique el procedimiento contrario. Tengo un SOAPFault con un xml en el detail y lo quiero serializar.

Este es el mensaje que me llega desde el WebService al que me conecto:

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Body>
                <soapenv:Fault>
                        <faultcode>soapenv:Server</faultcode>
                        <faultstring>0301 - Organismo no autorizado 'P3600000H' 'CDISFWS01'</faultstring>
                        <faultactor>CDISFWS01</faultactor>
                        <detail>
                                <Atributos xmlns="http://www.map.es/scsp/esquemas/V2/soapfaultatributos">
                                        <IdPeticion>1390408700541</IdPeticion>
                                        <NumElementos>1</NumElementos>
                                        <TimeStamp>2014-01-22T17:37:49.601+01:00</TimeStamp>
                                        <Estado>
                                                <CodigoEstado>0301</CodigoEstado>
                                                <CodigoEstadoSecundario />
                                                <LiteralError>Organismo no autorizado 'P3600000H' 'CDISFWS01'</LiteralError>
                                                <TiempoEstimadoRespuesta>0</TiempoEstimadoRespuesta>
                                        </Estado>
                                        <CodigoCertificado>CDISFWS01</CodigoCertificado>
                                </Atributos>
                        </detail>
                </soapenv:Fault>
        </soapenv:Body>
</soapenv:Envelope>

Como lo trato:

	public String realizarConsulta(String datosPeticion) {
		try {
			// llamada al servicio, la parte, en la que va todo bien.
			// ...
		} catch (Exception e) {
			if(e instanceof javax.xml.ws.soap.SOAPFaultException){
				javax.xml.soap.SOAPFault fault = ((javax.xml.ws.soap.SOAPFaultException) e).getFault();
				es.map.scsp.esquemas.v2.soapfaultatributos.Atributos atributos = getSoapfaultatributo(fault);
				if(atributos != null){
					String codigoEstado = atributos.getEstado().getCodigoEstado();
					String literalError = atributos.getEstado().getLiteralError();
					return errorMesagge(codigoEstado, literalError);
				}else{
					String faultCode = fault.getFaultCode();
					String faultString = fault.getFaultString();
					return errorMesagge(faultCode, faultString);					
				}
			}else{
				LOGGER.error("ERROR", e);				
				return errorMesagge(null, e.getMessage());
			}
		}
	}

	@SuppressWarnings("unchecked")
	private es.map.scsp.esquemas.v2.soapfaultatributos.Atributos getSoapfaultatributo(javax.xml.soap.SOAPFault fault) {
		es.map.scsp.esquemas.v2.soapfaultatributos.Atributos atributos = null;
		try {
			javax.xml.soap.Detail detail = fault.getDetail();
			if(detail != null){
				Iterator<DetailEntry> iterator = detail.getDetailEntries();
				while(iterator.hasNext()){
					DetailEntry detailEntry = (DetailEntry) iterator.next();

					Document document = detailEntry.getOwnerDocument(); 
					DOMImplementationLS domImplLS = (DOMImplementationLS) document .getImplementation(); 
					LSSerializer serializer = domImplLS.createLSSerializer(); 
					String str = serializer.writeToString(detailEntry);
					str = str.replace("UTF-16", "UTF-8");
					LOGGER.trace("detailEntry: "+ str);
					
					Object xmlBinderObjeto = xmlBinder.unmarshal(str);

					if(xmlBinderObjeto instanceof es.map.scsp.esquemas.v2.soapfaultatributos.Atributos){
						atributos = (es.map.scsp.esquemas.v2.soapfaultatributos.Atributos) xmlBinderObjeto;
					}
				}
			}
		} catch (Exception e) {
			LOGGER.warn("ERROR al deserializar ATRIBUTOS del SOAPFault. ", e);
		}
		
		return atributos;
	}

Ahora bien, por ejemplo, no tienes el xsd del mensaje o te lo han cambiado si avisar…

	@SuppressWarnings("unchecked")
	@Override
	public String realizarConsulta(String datosPeticion) {
		try {
			// llamada al servicio, la parte, en la que va todo bien.
			// ...
		} catch (Exception e) {
			if(e instanceof javax.xml.ws.soap.SOAPFaultException){
				javax.xml.soap.SOAPFault fault = ((javax.xml.ws.soap.SOAPFaultException) e).getFault();
				String faultCode = fault.getFaultCode();
				String faultString = fault.getFaultString();
				LOGGER.info("faultCode: "+faultCode);
				LOGGER.info("faultString: "+faultString);
				
				javax.xml.soap.Detail detail = fault.getDetail();
				if(detail != null){
					Iterator<DetailEntry> iterator = detail.getDetailEntries();
					while(iterator.hasNext()){
						DetailEntry detailEntry = (DetailEntry) iterator.next();
						String NamespaceUri_soapfaultatributos = "http://www.map.es/scsp/esquemas/V2/soapfaultatributos";
						if(NamespaceUri_soapfaultatributos.equalsIgnoreCase(detailEntry.getElementQName().getNamespaceURI())){
							Iterator<?> it = detailEntry.getChildElements();
							String codigoEstado = null; 
							String literalError = null;
							String idPeticion = null;
							String timeStamp = null;
							while(it.hasNext()){
								Object object = it.next();
								if(object instanceof SOAPElement){
									SOAPElement element = (SOAPElement) object;
									String name = element.getLocalName();
									if("IdPeticion".equalsIgnoreCase(name)){
										idPeticion = element.getValue();
										LOGGER.info("IdPeticion: "+idPeticion);
									}else if("TimeStamp".equalsIgnoreCase(name)){
										timeStamp = element.getValue();
										LOGGER.info("TimeStamp: "+timeStamp);
									}else if("Estado".equalsIgnoreCase(name)){
										Iterator<?> itElements = element.getChildElements();
										while(itElements.hasNext()){
											Object objeto = itElements.next();
											if(objeto instanceof SOAPElement){
												SOAPElement elementHijo = (SOAPElement) objeto;
												String nameHijo = elementHijo.getLocalName();
												if("CodigoEstado".equalsIgnoreCase(nameHijo)){
													codigoEstado = elementHijo.getValue();
													LOGGER.info("CodigoEstado: "+codigoEstado);
												}else if("LiteralError".equalsIgnoreCase(nameHijo)){
													literalError = elementHijo.getValue();
													LOGGER.info("LiteralError: "+literalError);
												}
											}
										}
									}
								}
							}

						}

					}
				}

				return errorMesagge(faultCode, faultString);
			}else{
				LOGGER.error("ERROR", e);				
				return errorMesagge(null, e.getMessage());
			}
		}
	}

Ni decir falta que habria que refactorizar un poco 😉 jeje.

javax.xml.soap.DetailEntry to xml