2011-07-05 15 views
9

Im trabajando en un proyecto Java donde necesito leer algunos objetos de un archivo XML, hacer algún procesamiento que alterará los atributos del objeto y luego escribir el Objeto en otro archivo XML. A tal fin, estoy usando JAXB con su clasificación y el capacidades unmarshalling, cada uno de ellos en un método, como esto:Objeto XML JAXB Ordenamiento sin prefijos de espacio de nombres

private MyObject unmarshallXMLFile(String file) { 
    MyObject t=null; 
    try { 
     jc = JAXBContext.newInstance("foo.bar"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     unmarshaller.setSchema(sf.newSchema(new File("MySchema.xsd"))); 
     t = (Task) unmarshaller.unmarshal(new File(file)); 
    } catch (JAXBException e) { 
     e.printStackTrace(); 
    } catch (SAXException e) { 
     e.printStackTrace(); 
    } 
    return t; 
} 

private void marshallXMLFile(String file) { 
    task.setReplay(Boolean.TRUE); 
    Marshaller marshaller; 
    try { 
     marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true)); 
     marshaller.marshal(task, new FileOutputStream(file)); 
    } catch (JAXBException e) { 
     e.printStackTrace(); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 

} 

El problema es que los prefijos de espacio de nombres generados automáticamente, como NS2 o NS3 siguen apareciendo en el archivo de salida, y luego cuando quiero reutilizar estos archivos con el método unmarshallXMLFile (volveré a usar los archivos de salida como entrada más adelante) no se validará contra el esquema, y ​​arroja una org.xml.sax.SAXParseException. Estos son los archivos que he escrito: Esquema

XML: MySchema.xsd

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/MySchema" 
    xmlns:spm="http://www.example.org/MySchema" 
    elementFormDefault="qualified" 
    attributeFormDefault="qualified"> 

    <element name="task" > 
     <complexType> 
      <sequence> 
       <element name="replay" type="boolean" default="false"/> 
       <element name="threads" type="spm:spThread" maxOccurs="unbounded" minOccurs="1" /> 
      </sequence> 
     </complexType> 
    </element> 

    <complexType name="spThread"> 
     <sequence> 
      <element name="SPThreadID" type="int" /> 
      <element name="durtime" minOccurs="0" default="0"> 
       <simpleType> 
        <restriction base="int"> 
         <minInclusive value="0" /> 
        </restriction> 
       </simpleType> 
      </element> 
      <element name="minexecutions" minOccurs="0" default="0"> 
       <simpleType> 
        <restriction base="int"> 
         <minInclusive value="0" /> 
        </restriction> 
       </simpleType> 
      </element> 
      <element name="numThreads" type="int" /> 
      <element name="procedures" type="spm:procedure" minOccurs="1" 
       maxOccurs="unbounded" /> 
     </sequence> 
    </complexType> 

    <complexType name="procedure"> 
     <sequence> 
      <element name="id" type="int" minOccurs="1" /> 
      <element name="name" type="string" minOccurs="1" /> 
      <element name="weight" minOccurs="1"> 
       <simpleType> 
        <restriction base="int"> 
         <minInclusive value="0" /> 
         <maxInclusive value="100" /> 
        </restriction> 
       </simpleType> 
      </element> 
      <element name="parameterPool" type="spm:parameter" nillable="true" 
       minOccurs="0" maxOccurs="unbounded" /> 
     </sequence> 
    </complexType> 

    <complexType name="parameter"> 
     <sequence> 
      <element name="name" type="string" minOccurs="1" /> 
      <element name="dataType" type="spm:parameterDataType" default="integer"/> 
      <element name="parmType" type="spm:parameterType" default="in" 
       minOccurs="0" /> 
      <element name="minValue" type="string"/> 
      <element name="maxValue" type="string"/> 
      <element name="value" type="string"/> 
     </sequence> 
    </complexType> 

    <simpleType name="parameterDataType"> 
     <restriction base="string"> 
      <enumeration value="integer" /> 
      <enumeration value="varchar" /> 
      <enumeration value="char" /> 
     </restriction> 
    </simpleType> 

    <simpleType name="parameterType"> 
     <restriction base="string"> 
      <enumeration value="in" /> 
      <enumeration value="out" /> 
      <enumeration value="in_out" /> 
     </restriction> 
    </simpleType> 

</schema> 

archivo de entrada:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<task xmlns="http://www.example.org/MySchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/MySchema MySchema.xsd "> 
    <replay>true</replay> 
    <threads> 
     <SPThreadID>0</SPThreadID> 
     <durtime>10</durtime> 
     <minexecutions>2</minexecutions> 
     <numThreads>3</numThreads> 
     <procedures> 
      <id>1</id> 
      <name>run</name> 
      <weight>15</weight> 
      <parameterPool> 
       <name>energy</name> 
       <dataType>integer</dataType> 
       <parmType>in</parmType> 
       <minValue>10</minValue> 
       <maxValue>50</maxValue> 
       <value>11</value>     
      </parameterPool> 
      <parameterPool> 
       <name>speed</name> 
       <dataType>integer</dataType> 
       <parmType>in</parmType> 
       <minValue>12</minValue> 
       <maxValue>80</maxValue> 
       <value>13</value>         
      </parameterPool> 
     </procedures> 
    </threads> 
</task> 

archivo de salida (sin ningún tratamiento en absoluto: simplemente unmarshalling y cálculo de referencias de vuelta con los métodos mencionado anteriormente)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ns2:task xmlns="http://www.example.org/MySchema" xmlns:ns2="http://www.example.org/MySchema.xsd"> 
    <replay>true</replay> 
    <threads> 
     <SPThreadID>0</SPThreadID> 
     <durtime>10</durtime> 
     <minexecutions>2</minexecutions> 
     <numThreads>3</numThreads> 
     <procedures> 
      <id>1</id> 
      <name>run</name> 
      <weight>15</weight> 
      <parameterPool> 
       <name>energy</name> 
       <dataType>integer</dataType> 
       <parmType>in</parmType> 
       <minValue>10</minValue> 
       <maxValue>50</maxValue> 
       <value>11</value> 
      </parameterPool> 
      <parameterPool> 
       <name>speed</name> 
       <dataType>integer</dataType> 
       <parmType>in</parmType> 
       <minValue>12</minValue> 
       <maxValue>80</maxValue> 
       <value>13</value> 
      </parameterPool> 
     </procedures> 
    </threads> 
</ns2:task> 

excepción (cuando se utiliza nuevamente el archivo de salida s una entrada):

javax.xml.bind.UnmarshalException 
- with linked exception: 
[org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found.] 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:326) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:500) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:206) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:148) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:153) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:180) 
    at Test.main(Test.java:48) 
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: The declaration of the element'ns3:task' could not be found. 
    at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source) 
    at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source) 
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source) 
    at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source) 
    at org.apache.xerces.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source) 
    at org.apache.xerces.impl.xs.XMLSchemaValidator.startElement(Unknown Source) 
    at org.apache.xerces.jaxp.validation.XMLSchemaValidatorHandler.startElement(Unknown Source) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:85) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:113) 
    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source) 
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source) 
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source) 
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source) 
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) 
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) 
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) 
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source) 
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:202) 
    ... 6 more 

he estado leyendo sobre el tema y trató un montón de respuestas relacionadas, pero ninguna de ellas parece eliminar los prefijos. Fui a través de este guide pero la versión de jaxb que estoy usando no es compatible con NamespacePrefixMapper. Intenté usar las anotaciones como se describe en here para configurar los prefijos pero eso no funcionaría.

Quizás haya una manera de deshacerse de estos prefijos de espacio de nombres: todos los foros, respuestas y discusiones que he encontrado hablan sobre personalizar estos prefijos, solo quiero deshacerme de ellos. Pero de alguna manera me hace pensar que me falta algo tanto en mi archivo de entrada como en el esquema. Están bien escritos? Diría que ahí está el problema, porque es la primera vez que trabajo con xml y xsd a esta profundidad, y lo que he hecho solo se basa en lo que he encontrado en línea. Cualquier consejo sobre la mejora de los diseños xml y xsd sería muy apreciado

¿Debería utilizar algún tipo de prefijos en el archivo de entrada o en el esquema para que el framework JAXB no genere prefijos aleatorios en el momento de la clasificación?

gracias de antemano, espero que ustedes puedan ayudarme.

-

Muchas gracias por la respuesta. De esa manera puedo usar NamespacePrefixMapper. Sin embargo, cuando lo uso, mi código mantiene lanzar excepciones cuando lo funciono:

Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name javax.xml.bind.Messages, locale de_DE 
    at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:863) 
    at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:832) 
    at java.util.ResourceBundle.getBundle(ResourceBundle.java:576) 
    at javax.xml.bind.Messages.format(Messages.java:47) 
    at javax.xml.bind.Messages.format(Messages.java:36) 
    at javax.xml.bind.PropertyException.<init>(PropertyException.java:99) 
    at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty(AbstractMarshallerImpl.java:349) 
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:527) 
    at Test.main(Test.java:95) 

me encontré con que tiene que hacer algo con un archivo .properties: no estoy usando nada igual, que no he cambiado nada .

+0

similar tema/posible duplicado: http://stackoverflow.com/questions/1982977/is-it-possible-to-custo mize-the-namespace-prefix-that-jaxb-uses-when-marshalling –

Respuesta

3

Bueno, después de algunas investigaciones, he intentado usar la etiqueta @XMLElement en todos los atributos de las clases que estoy tratando de serializar, se especificará claramente cuál era mi espacio de nombres, y el uso de la misma en todos los atributos:

@XmlElement(required = true, name="myObjectPool", namespace="http://www.example.org/StoredProceduresSchema") 
    protected List<MyObject> myObjectPool; 

funcionó a la perfección: no hay espacios de nombres más extraños en el archivo formateado.

Quiero agradecerle su respuesta: lo intenté también, pero tengo una excepción relacionada con el paquete de idiomas. Me alegro de que este enfoque más simple resolvió el problema.

+0

podemos usar el prefijo en ese @XmlElement –

3

Trate de usar un NamespacePrefixMapper:

NamespacePrefixMapper mapper = new NamespacePrefixMapper() { 
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { 
     return ""; 
    } 
}; 
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper); 
+0

Muchas gracias por la respuesta. De esa manera puedo usar NamespacePrefixMapper. Sin embargo, cuando lo uso, mi código sigue arrojando excepciones cuando lo ejecuto: – Lak

11

En lugar de especificar el atributo de espacio de nombres @XmlElement en cada elemento, es más fácil anotar a nivel del paquete. Para ello, crea un archivo package-info.java justo debajo del paquete que deseas anotar.

Por ejemplo, si desea anotar el paquete org.example, a continuación, un archivo llamado package-info.java debe ser colocado dentro de la org/ejemplo, con el siguiente contenido:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/StoredProceduresSchema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package org.example; 

Es importante tener en cuenta que se debe anotar cada paquete que contiene clases que su plan debe reunir o que son referenciadas por ellos.

Espero que esto ayude :)

1

Java 7/8 solución

Este problema está relacionado con la implementación predeterminada Proveedor JAXB. Encontré una solución usando una implementación diferente: EclipseLink MOXy.

1. Añadir la dependencia en pom.xml
<dependency> 
    <groupId>org.eclipse.persistence</groupId> 
    <artifactId>org.eclipse.persistence.moxy</artifactId> 
    <version>2.5.0</version> 
</dependency>` 
2. crear un jaxb.properties archivo que contiene la siguiente línea
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

mover el archivo en el paquete modelo

3. crear archivo-paquete. Java en el paquete modelo
@XmlSchema(xmlns = { @XmlNs(prefix = "video", namespaceURI = "http://www.google.com/schemas/sitemap-video/1.1"), 
     @XmlNs(prefix = "", namespaceURI = "http://www.sitemaps.org/schemas/sitemap/0.9")}) 

package it.my.sitemap.model; 

import javax.xml.bind.annotation.XmlNs; 
import javax.xml.bind.annotation.XmlSchema; 
Cuestiones relacionadas