When marshalling an object to XML with JAXB, it automatically generates namespace prefixes like ns2:
. The system I have to communicate with unfortunately doesn't work with these default prefixes (despite the fact that the XML is perfectly valid), so I want to create a mapping of the prefixes there should be for all different namespaces. The XSD is also used for other projects, so I would prefer not to have to make any changes in it.
I found 2 solutions in other answers and on other websites:
Use a namespace prefix mapper class. Sounds perfect, but unfortunately this is no longer an option, as the relevant property no longer exists on the marshaller (using jakarta.xml.bind:jakarta.xml.bind-api:4.0.0
).
Add XmlNs
annotations in package-info.java
. This seems like the only option that's left (besides search/replace in the XML file after marshalling), but this file is generated: all Java classes are generated from the XSD with an XJC task using Gradle. Manual additions of such annotations to the package-info files would be overwritten by the next run of a generate task.
My questions: is there a way to provide JAXB with my own prefix mapping? Or is there a way to have XJC generate those XmlNs annotations automatically?
HiSrc HyperJAXB Annox provides an XJC plugin that can add Java annotations to your generated package-info.java
. You can add an annotation to specify a custom xmlns
. To use it, add the jar (below) to your XJC classpath and add this argument to your XJC invocation, -Xannotate
.
XJC Add-On Jar
<groupId>org.patrodyne.jvnet</groupId>
<artifactId>hisrc-hyperjaxb-annox-plugin</artifactId>
<version>2.1.0</version>
Configure the annox
extension in your bindings file at any one complexType
, like this ...
Bindings Example
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings jaxb:version="3.0"
xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://jvnet.org/basicjaxb/xjc/annox"
jaxb:extensionBindingPrefixes="annox"
>
<jaxb:bindings schemaLocation="PurchaseOrder.xsd" node="/xsd:schema" >
<jaxb:bindings node="xsd:element[@name='purchaseOrder']/xsd:complexType">
...
<annox:annotatePackage>
@jakarta.xml.bind.annotation.XmlSchema(
xmlns = {
@jakarta.xml.bind.annotation.XmlNs(prefix = "po", namespaceURI = "http://example.org/po")
})
</annox:annotatePackage>
...
</jaxb:bindings>
</jaxb:bindings>
Each time you run your XJC action in your build, the package-info.java
class should include your defined XmlNs
prefix.
Disclaimer: I am the maintainer of the forked HiSrc projects.
BTW, in the Eclipse JAXB implementation, the NamespacePrefixMapper
and its property can be found at:
Mapper: org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper
Used By: org.glassfish.jaxb.runtime.v2.runtime.MarshallerImpl
Property: org.glassfish.jaxb.namespacePrefixMapper