1

I have an XSD that defines the following schema:

<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns="http://example.com/2010/aa/"
       xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
       xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
       xmlns:aa="http://example.com/2010/aa/"
       targetNamespace="http://example.com/2010/aa/"
       elementFormDefault="qualified">
...
<xs:element name="user" type="aa:User"/>
<xs:complexType name="User">
  <xs:sequence>
      <xs:element ref="aa:firstName" minOccurs="0" maxOccurs="1"/>
      <xs:element ref="aa:lastName" minOccurs="0" maxOccurs="1"/>
      ...
      <xs:any namespace="##targetNamespace" processContents="skip" maxOccurs="unbounded" />
  </xs:sequence>
  <xs:anyAttribute processContents="skip" />
</xs:complexType>

<xs:element name="profile" type="aa:Profile"/>
<xs:complexType name="Profile">
 <xs:sequence>
    <xs:element ref="aa:username" minOccurs="0" maxOccurs="1"/>
    <xs:element ref="aa:accountStatus" minOccurs="0" maxOccurs="1" />
    <xs:element ref="aa:roleid" minOccurs="0" maxOccurs="1"/>
    ...
    <xs:element ref="aa:userid"/>
 </xs:sequence>
 <xs:anyAttribute processContents="skip" />
</xs:complexType>

When JAXB is marshalling the generated Objects it defines the following:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<user xmlns:ns2="http://example.com/2010/aa/">...</user>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<profile xmlns="http://example.com/2010/aa/">...</profile>

See how one namespace is xmlns:ns2 and the other one is xmlns. This is because all the elements of user are qualified for the aa namespace but the ones defined by the xs:any tag, hence the need to define two namespaces.

Profile doesn't have a xs:any tag and doesn't need to define more than one namespaces. This is my interpretation, since if I remove the xs:any from the user definition it will remove the ns2 from the generated XML.

How can I tell JAXB that both the targetNamespace and aa are the same namespace so it doesn't include both?

Iker Jimenez
  • 7,105
  • 9
  • 49
  • 46

2 Answers2

3

You could try to use a NamespacePrefixMapper to override how the prefixes are generated in the first place:

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

I'm returning "" there, so there will be only a default prefix; implement a more sophisticated version as required.

This does create a dependency on a Sun class, which is a problem caused by JAXB. Please review this other post. The answer at the bottom shows how to modify package-info.java to achieve the same.

Community
  • 1
  • 1
xcut
  • 6,219
  • 1
  • 33
  • 27
1

Alternatively, instead of using a proprietary Metro JAXB extension, you could use MOXy JAXB. MOXy will use the namespace prefixing defined in the @XmlSchema package level annotation.

For more information see:

Community
  • 1
  • 1
bdoughan
  • 147,609
  • 23
  • 300
  • 400