java ee - javaee - JAXB Marshaller: la salida de StringWriter tiene un valor de etiqueta truncada
jaxb tutorial (1)
Quiero asignar un objeto java a una cadena xml. Por lo tanto, me dieron un esquema del cual genero las clases de JAXB. Hay un método set (que corresponde a un elemento de tipo hexbinary en el esquema) donde tengo que establecer una cadena. El tamaño de la cadena es de aproximadamente 2566. Después de configurar los datos en el objeto a través de los métodos setter, invoco el argumento marshaller passing stringWriter.
Pero al imprimir stringWriter, veo que está truncado. No veo los 2566 caracteres completos.
¿Qué está mal? ¿Algunas ideas?
Gracias!
Actualizar:
Creo que encontré el problema. ¡Tengo que encontrar un título adecuado ya que mi razonamiento del problema era incorrecto! El problema es el siguiente: Tengo un elemento "hexbinary" en mi esquema. La clase generada tiene un método set / get correspondiente. Para establecer el valor, he usado el método HexEncodeString del paquete apache commons y me di cuenta de que el marcador muestra 36383639 en la etiqueta hexbinary para un String "hola" cuya codificación Hex real es 6869 :( Por lo tanto, el problema es que el xml después de calcular tiene una etiqueta valor con # caracteres más grandes que el original y sin truncar como pensé antes.
Gracias al código de Blaise Doughan . Lo he modificado y reproducido este problema.
Primero un esquema de ejemplo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Root">
<xs:sequence>
<xs:element name="string" type="xs:string" minOccurs="0"/>
<xs:element name="a" type="xs:hexBinary" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Con esto genere la clase ObjectFactory y la clase Root. Tuve que modificar la clase ObjectFactory para incluir JAXBElement para poder pasar esto al Marshaller. Con estos tomé la clase Demo de Blaise Doughan y la modifiqué como:
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
// The object factory
ObjectFactory objFactory = new ObjectFactory();
Root root = new Root();
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(val.getBytes());
System.out.println("val="+val);
System.out.println("getString ="+root.getString());
System.out.println("getArr="+new String(root.getArr()));
// Marshal the object to a StringWriter
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(objFactory.createRoot(root),stringWriter);
// marshaller.marshal(root, stringWriter);
// Convert StringWriter to String
String xml = stringWriter.toString();
System.out.println(xml);
// Unmarshal the XML and check length of long String
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(root.getString().length());
System.out.println(root.getString());
System.out.println(new String(root.getArr()).length());
System.out.println(new String(root.getArr()));
}
}
El resultado que obtengo es:
val=6869
getString =hi
getArr=6869
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:Root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:ns3="http://example.com/root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>hi</string>
<arr>36383639</arr>
</ns3:Root>
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://example.com/root", local:"Root"). Expected elements are (none)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:631)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:236)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:231)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1038)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:467)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:448)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:400)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:626)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3103)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:922)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)
at example.Demo.main(Demo.java:43)
¿Por qué es arr etiqueta 36383639 y no 6869?
NUEVA RESPUESTA
En su código de muestra, val
es la representación str.getBytes()
de str.getBytes()
. Pero el valor que está configurando en la propiedad arr
es los bytes de la cadena codificada hexadecimal.
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(val.getBytes());
Creo que lo que quieres hacer es lo siguiente:
String str = new String("hi");
String val = Hex.encodeHexString(str.getBytes());
root.setString(str);
root.setArr(str.getBytes());
Que producirá la siguiente salida
val=6869
getString =hi
getArr=hi
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xsi:schemaLocation="http://www.example.com/schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string>hi</string>
<a>6869</a>
</root>
Dicho de otra manera
String str = new String("hi");
System.out.print("String: " + str);
System.out.println(" hexBinary: " + Hex.encodeHexString(str.getBytes()));
String val = Hex.encodeHexString(str.getBytes());
System.out.print("String: " + val);
System.out.println(" hexBinary: " + Hex.encodeHexString(val.getBytes()));
Se producirá:
String: hi hexBinary: 6869
String: 6869 hexBinary: 36383639
RESPUESTA ORIGINAL
No he podido reproducir el problema que estás viendo. Estoy usando un tamaño de String
de 500000
. Debajo está lo que he intentado (¿esta muestra funciona para usted?). ¿Es posible que el truncamiento se deba a la consola para la que está escribiendo la cadena larga?
Manifestación
package forum12146217;
import java.io.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
// Build a long String
StringBuilder stringBuilder = new StringBuilder();
for(int x=0; x<500000; x++) {
stringBuilder.append("a");
}
Root root = new Root();
root.setString(stringBuilder.toString());
System.out.println(root.getString().length());
// Marshal the object to a StringWriter
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
StringWriter stringWriter = new StringWriter();
marshaller.marshal(root, stringWriter);
// Convert StringWriter to String
String xml = stringWriter.toString();
//System.out.println(xml);
// Unmarshal the XML and check length of long String
Unmarshaller unmarshaller = jc.createUnmarshaller();
Root unmarshalledRoot = (Root) unmarshaller.unmarshal(new StringReader(xml));
System.out.println(unmarshalledRoot.getString().length());
}
}
Raíz
package forum12146217;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Root {
private String string;
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
}
Salida
500000
500000