¿Es posible personalizar el prefijo de espacio de nombres que JAXB utiliza al clasificar una cadena?


Por ejemplo, tengo un esquema simple que importa otro esquema. El segundo esquema (urna: just: attributes, just-attributes.xsd) solo define un grupo de atributos.

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.org/MySchema"
    xmlns:tns="http://www.example.org/MySchema" 
    elementFormDefault="qualified"
    xmlns:ja="urn:just:attributes">

    <import schemaLocation="just-attributes.xsd" namespace="urn:just:attributes"/>

    <element name="MyElement">
        <complexType>
            <attributeGroup ref="ja:AttributeGroup"/>
        </complexType>
    </element>
</schema>

Estoy usando la tarea Metro xjc Ant para generar clases fuera de este esquema. El problema que me estoy encontrando es que la aplicación de terceros con la que estoy interactuando es peculiar acerca de los espacios de nombres. En este caso necesito un valor de cadena, así que tengo que serializarlo. Yo uso código repetitivo para esto.

private static <T> String marshal(T object) throws JAXBException{
    OutputStream outputStream = new ByteArrayOutputStream();
    JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.marshal(object, outputStream);
    return outputStream.toString();
}

Que me da algo a lo largo de las líneas de

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:MyElement xmlns:ns1="urn:just:attributes" xmlns:ns2="http://www.example.org/MySchema" ns1:attrib1="1234" ns1:attrib2="5678"/>

El problema que tengo es que este tercero espera algo como xmlns:thirdpartyns="urn:just:attributes", es decir, están analizando en función del nombre dado al espacio de nombres. tiene ser "third partyns" para que su software funcione.

¿Alguien sabe de una forma de evitar esto, sin hacer un find y replace en la cadena resultante? ¿Una regla vinculante personalizada tal vez?

Author: JoshC13, 2009-12-31

4 answers

Http://hwellmann.blogspot.com/2011/03/jaxb-marshalling-with-custom-namespace.html

Esto muestra cómo hacerlo.

Otro: http://www.systemmobile.com/?p=280

Bits de clave en caso de que el enlace muera también:

La clase NamespacePrefixMapper, que se encuentra en com.sol.XML.unir.paquete marshaller. La clase abstracta tiene un método para implementar:

public abstract String getPreferredPrefix(  
     String namespaceUri,         
     String suggestion,         
     boolean requirePrefix); 

Entonces

Marshaller marshaller =        
    jaxbContext.createMarshaller();        
marshaller.setProperty(”com.sun.xml.bind.namespacePrefixMapper”,        
    new MyNamespacePrefixMapper());  

Si también estás usando javax.XML.xpath.XPath, su NamespacePrefixMapper también puede implementar javax.XML.espacio de nombres.NamespaceContext, centralizando la personalización del espacio de nombres en una sola clase.

 27
Author: DaveC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-10 20:50:28

Probé que en Java SE6 y requiere un pequeño cambio en comparación con la solución para Java SE 5 (como se describe anteriormente):

    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
    m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", mapper);

Así que la tercera propiedad de arriba contiene el .internal. adicional en el nombre del paquete comparado con la versión de Java SE5. Lo que aún no he descubierto es cómo decirle al Marshaller qué URI de espacio de nombres se convierte en el espacio de nombres predeterminado (""). Si sobrescribo el método getPreferredPrefix() y devuelvo una cadena vacía, el Marshaller tiene problemas con los atributos de escritura del espacio de nombres predeterminado (en este caso crea un nuevo espacio de nombres llamado ns1)

 11
Author: basZero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:29:43

Yo tenía la misma pregunta. En package-info.java (si no lo tiene, puede crearlo manualmente) agregue la parte xmlns:

@javax.xml.bind.annotation.XmlSchema(xmlns = {
        @javax.xml.bind.annotation.XmlNs(namespaceURI = "urn:just:attributes", prefix = "thirdpartyns") }, 
        elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
 6
Author: Weslor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-28 08:03:16

Hay una forma de hacer esto, que usa una clase interna de implementación JAXB llamada NamespacePrefixMapper. En el JAXB RI, esto está en com.sun.xml.bind.marshaller, pero en Java6, está en com.sun.xml.internal.bind.marshaller.

Esta es una clase abstracta, que puede subclasificar e implementar el método abstracto que asigna URI de espacio de nombres a prefijos.

Luego inyecta una instancia de esa subclase en el marshaller:

JAXBContext context = ...
Marshaller marshaller = context.createMarshaller();
NamespacePrefixMapper prefixMapper = new MyPrefixMapperImpl();
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", prefixMapper);

El nombre de la propiedad va a ser diferente para la versión Java6, pero te haces una idea.

Nota que esta es una clase interna de implementación JAXB, por lo que no hay garantía de que estará allí en futuras versiones.

 0
Author: skaffman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-31 00:18:55