viernes, 9 de noviembre de 2012

problema unmarshalling tabs and enters in XML

JAXB Unmarshalling, XMLAdapter, bindings y familia. Contexto: App que recibe un XML over HTTP y lo digiere usando un XSD provisto con anterioridad. Problema: El XML recibido tiene tabs (\t) y enters (\n) y al final del parseo automatico de JAXB los campos tipo String incuyen estos caracteres. i.e. "\t\teuropa\n\t\t" en vez del esperado "europa" Codigo:

    public void init() {
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", port, PlainSocketFactory.getSocketFactory()));
ThreadSafeClientConnManager connManager = new ThreadSafeClientConnManager(schemeRegistry);
httpClient = new DefaultHttpClient(connManager);
AuthScope authscope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);
Credentials credentials = new UsernamePasswordCredentials(username, password);
httpClient.getCredentialsProvider().setCredentials(authscope, credentials);

try {
context = JAXBContext.newInstance("com.matias.api");
} catch (JAXBException e) {
throw new IllegalStateException("Couldn't initialise Matias API JAXB context", e);
}
}

private JAXBElement<?> unmarshallResponse(HttpResponse response) {
try {
InputStream content = response.getEntity().getContent();
String string = EntityUtils.toString(response.getEntity());
System.out.println(string);
return (JAXBElement<?>) context.createUnmarshaller().unmarshal(content);
....
Intento: Trate de agregarle un adapter (NormalizedStringAdapter) al unmarshaller pero solo funciona si existe la annotation@XmlSchemaType en el pojo y como estoy generando los pojos desde nu XSD esta opcion no es conveniente para mi.
Solucion: Agregar un binding durante la generacion java desde el XSD. Configuracion del maven plugin:
      <plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.0</version>
    <configuration>
     <extension>true</extension>
     <forceRegenerate>true</forceRegenerate>
     <episode>false</episode>
     <bindingDirectory>src/main/resources</bindingDirectory>
     <bindingIncludes>
      <bindingInclude>binding.xml</bindingInclude>
     </bindingIncludes>     
    </configuration>
    <executions>
     <execution>
      <id>api</id>
      <phase>generate-sources</phase>
      <goals>
       <goal>generate</goal>
      </goals>
      <configuration>
       <schemaIncludes>
        <include>lalala.xsd</include>
       </schemaIncludes>
       <generatePackage>com.matias.api</generatePackage>
      </configuration>
     </execution>
    </executions>
   </plugin>


Binding file:

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <globalBindings>
  <javaType name="java.lang.String" xmlType="xs:string"
   parseMethod="com.gambit.api.unmarshaller.StringNormalizer.unmarshal" />
 </globalBindings>
</bindings>

The parser class you should include when using the maven XSD plugin must have the an static method with the signature specified in the binding. You can create a method based in NormalizedStringAdapter method:

public class StringNormalizer {
    public static String unmarshal(String text) {
...
}

No hay comentarios: