javaapiforkml icon indicating copy to clipboard operation
javaapiforkml copied to clipboard

Default output from Marshaller should not include the namespace qualification

Open rdamus opened this issue 6 months ago • 2 comments

i have been using this library for over a decade and recently had to upgrade to v3.x because of java17 compliance, etc.

i took KML files generated by code that i haven't touched in years and fed them to a Google Maps overlay and receive an INVALID_KML error!

this was confusing, but seems to be because the library has changed it's default behavior to now prepend kml: to all the tags in the document.

  1. this should be better documented, as it is a hidden "feature" at the moment
  2. suggest reverting this to jakarta.xml.bind.annotation.XmlNsForm.UNQUALIFIED (UNSET is apparently not advised) and let the user decide if they want namespace qualification through JAXB or not
  3. publish a separate version of the library - one with namespacing, one without?

i found this in the package-info.java:

@jakarta.xml.bind.annotation.XmlSchema(
    namespace = "http://www.opengis.net/kml/2.2",
    xmlns = {
        @jakarta.xml.bind.annotation.XmlNs( prefix = "kml", namespaceURI = "http://www.opengis.net/kml/2.2" )
        // ... other namespaces like gx, atom, xal
    },
    elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED
)
package de.micromata.opengis.kml.v_2_2_0;

rdamus avatar May 26 '25 17:05 rdamus

The workaround for this issue is to write a custom NamespacePrefixMapper - there is literally nothing else you can do given the changes to the jaxb-api from the Java days to the Jakarta ownership - spent way too long figuring this out.

import org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper

/**
 * Necessary since javaapiforkml:3.x as the new bindings only support jakarta.jaxb so we have to
 * remap the namespaceUri to a blank string otherwise Kml is generated with tags that contain
 * the 'kml' prefix for the uri
 *
 * ex: <kml:kml><kml:/kml>
 */
class KmlPrefixMapper extends NamespacePrefixMapper{
    @Override
    String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        namespaceUri == "http://www.opengis.net/kml/2.2" ? "" : suggestion
    }
}

and then you will need to use this mapper with a method like this (Groovy code, same as above):

String marshal(Kml kmlObject) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(
                "de.micromata.opengis.kml.v_2_2_0", // Package of the KML JAXB classes
                Kml.class.getClassLoader()        // ClassLoader that can see the KML classes
        )
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        StringWriter stringWriter = new StringWriter()
        marshaller.setProperty("org.glassfish.jaxb.namespacePrefixMapper", new KmlPrefixMapper())
        marshaller.marshal(kmlObject, stringWriter)
        def kmlString = stringWriter.toString()
        log.debug "marshalled: $kmlString"
        kmlString
    }

rdamus avatar May 27 '25 23:05 rdamus

Hi @rdamus

Thank you very much for researching this Rob - given your knowledge now in this area do you think there is anything we can do sensibly in the codebase to support these two usecases other than maintaining two versions of the library, or is all this static and not configurable?

Mark.

urbancamo avatar May 28 '25 08:05 urbancamo

Hi @rdamus

Thank you very much for researching this Rob - given your knowledge now in this area do you think there is anything we can do sensibly in the codebase to support these two usecases other than maintaining two versions of the library, or is all this static and not configurable?

Mark.

mark, sorry for not seeing this sooner. giving the user the option to manage the namespacing is ideal, imho

the latest jaxb processing system really only provides the hook for the namespace prefixing using NamespacePrefixMapper, so at the very least i'd promote this in your docs because it is really non obvious, especially if you are used to the previous version of the library.

to support a single library, i think you would change your package-info.java definition of elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED to UNQUALIFIED <--i have not tested this, but maybe you could publish a branch and write a test

rdamus avatar Sep 12 '25 16:09 rdamus

Boa Tarde, Desde Já Agradeço Pela Orientação e Atenção.

Obrigado.

at.te Alexandre Henrique

Em sex., 12 de set. de 2025, 13:28, rob d. @.***> escreveu:

rdamus left a comment (urbancamo/javaapiforkml#59) https://github.com/urbancamo/javaapiforkml/issues/59#issuecomment-3285972612

Hi @rdamus https://github.com/rdamus

Thank you very much for researching this Rob - given your knowledge now in this area do you think there is anything we can do sensibly in the codebase to support these two usecases other than maintaining two versions of the library, or is all this static and not configurable?

Mark.

mark, sorry for not seeing this sooner. giving the user the option to manage the namespacing is ideal, imho

the latest jaxb processing system really only provides the hook for the namespace prefixing using NamespacePrefixMapper, so at the very least i'd promote this in your docs because it is really non obvious, especially if you are used to the previous version of the library.

to support a single library, i think you would change your package-info.java definition of elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED to UNQUALIFIED <--i have not tested this, but maybe you could publish a branch and write a test

— Reply to this email directly, view it on GitHub https://github.com/urbancamo/javaapiforkml/issues/59#issuecomment-3285972612, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUUIVVPOGMVRBHAF4WSXGKT3SLYEHAVCNFSM6AAAAAB56EPYOOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTEOBVHE3TENRRGI . You are receiving this because you commented.Message ID: @.***>

ahcfph avatar Sep 12 '25 20:09 ahcfph

Boa Tarde, Início Pedido Perdão, Por Retornar o e-mail com a Resposta Incompleta. Só percebi quando Vizualizei, as Informações nos Comentários. Venho Justificar, que Não tenho o Conhecimento para Efetuar a Mudança dos Códigos Proposto nas Informações. Finalizando, Peço se Possível, os Senhores que Contém o Conhecimento para fazer a mudança do código Correto, Fico Grato. Mais Uma Vez, Obrigado pela a Oportunidade do Canal e Atenção.

Alexandre Henrique

Em sex., 12 de set. de 2025, 13:28, rob d. @.***> escreveu:

rdamus left a comment (urbancamo/javaapiforkml#59) https://github.com/urbancamo/javaapiforkml/issues/59#issuecomment-3285972612

Hi @rdamus https://github.com/rdamus

Thank you very much for researching this Rob - given your knowledge now in this area do you think there is anything we can do sensibly in the codebase to support these two usecases other than maintaining two versions of the library, or is all this static and not configurable?

Mark.

mark, sorry for not seeing this sooner. giving the user the option to manage the namespacing is ideal, imho

the latest jaxb processing system really only provides the hook for the namespace prefixing using NamespacePrefixMapper, so at the very least i'd promote this in your docs because it is really non obvious, especially if you are used to the previous version of the library.

to support a single library, i think you would change your package-info.java definition of elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED to UNQUALIFIED <--i have not tested this, but maybe you could publish a branch and write a test

— Reply to this email directly, view it on GitHub https://github.com/urbancamo/javaapiforkml/issues/59#issuecomment-3285972612, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUUIVVPOGMVRBHAF4WSXGKT3SLYEHAVCNFSM6AAAAAB56EPYOOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTEOBVHE3TENRRGI . You are receiving this because you commented.Message ID: @.***>

ahcfph avatar Sep 12 '25 21:09 ahcfph