3

I have about 100 (if not more) Java classes generated from a big XSD file via xjc.

That XSD file has upper-case names for its elements. Now, when I marshall one object from these generated Java classes, I have a few issues.

Sample XML produced by JAXB marshall:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<advertiser xmlns:ns2="http://p.t.com/service">
    <ns2:Name>TEST Adv 001</ns2:Name>
</advertiser>
  1. The names of the elements (but not those of the sub-elements) are produced by JAXB in lower-case. I need them to be upper-case (as they are in the XSD).

  2. There are some strange ns2: prefixes to the names of the elements e.g. I want the xmlns:ns2 in this example to become just xmlns, and the ns2:Name to become just Name. One answer here on SO suggested putting attributeFormDefault="unqualified" in the XSD, but seems that didn't help me either.

How can I solve these two issues?

I looked here for similar question but don't find one quite identical to mine. Also the answers there look pretty complicated and they ask to change the Java classes which I cannot do. Why should this be so complicated?!

Note that my Java classes are auto-generated, so I don't want to change them manually.

I wonder why the XSD says one thing, and the JAXB marshall process produces another thing. Shouldn't the JAXB marshall generate XML which is 100% compliant with the XSD?

Edit

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Advertiser", propOrder = {

})
public class Advertiser {

    @XmlElement(name = "TelID")
    protected Integer telID;

    @XmlElement(name = "Name")
    protected String name;

    @XmlElementRef(name = "Address", namespace = "http://p.t.com/service", type = JAXBElement.class)
    protected JAXBElement<String> address;

.............

Edit 2

    Advertiser adv = new Advertiser();
    adv.setName("TEST Adv 001");

    StringWriter sw = new StringWriter();
    JAXB.marshal(adv, sw);
    System.out.println(sw.toString());
halfer
  • 19,824
  • 17
  • 99
  • 186
peter.petrov
  • 38,363
  • 16
  • 94
  • 159

1 Answers1

0

1) Strange. Since you've generated classes from XSD they should have adequate annotations and if elements in XSD were uppercase, you should get @XmlElement annotations with uppercase element names. Post a couple of schema-derived classes, interesting what they look like. You are right that when you generate classes from an XSD, you should get XML (more or less) conforming to the XSD when marshalling. At least the case of elements should match. This is very strange, I can't explain it. Post your classes, we'll see.

2) See

Is it possible to customize the namespace prefix that JAXB uses when marshalling to a String?

Update.

Ok, now I see where the problem is. You marshal an instance of Advertiser, but it is just an @XmlType not a @XmlRootElement. So JAXB does not know in which root element it should be marshalled and does something by default which produces advertiser, lowcase, in empty namespace.

To solve this you could either add @XmlRootElement annotation or wrap your Advertiser instance into a JAXBElement.

For the latter check for the ObjectFactory class in the same package as the Advertiser class. You could the do (something like):

ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<Advertiser> advElement = objectFactory.createAdvertiser(adv);

Marshalling advElement should give you the correct element name.

When compiling XML Schemas, XJC generates such createXYZ(XYZ value) methods for each of the global elements.

lexicore
  • 42,748
  • 17
  • 132
  • 221
  • Thanks for trying to help. I added how the Advertiser class starts. – peter.petrov Feb 14 '18 at 14:14
  • I just put elementFormDefault="unqualified" in the XSD, and then the names of the sub-elements got generated without ns2. So in the example I posted I got instead of . – peter.petrov Feb 14 '18 at 14:19
  • The `Name` element is marshalled just as the annotation specifies, starting with uppercase. I'm not quite sure what the uppercase problem is, care to elaborate? – lexicore Feb 14 '18 at 14:22
  • `elementFormDefault="unqualified"` - well, this effectively removed namespace from the sub-elements. I don't think this is what you want. – lexicore Feb 14 '18 at 14:22
  • Hm... But isn't the presence of elementFormDefault="qualified" what makes this ns2 appear there in the sub-elements? – peter.petrov Feb 14 '18 at 14:29
  • To answer your previous question, the problem is that `advertiser` is marshalled in lower-case. Sorry I originally overlooked and thought that sub-elements are also marshalled in lowercase. – peter.petrov Feb 14 '18 at 14:31
  • Indirectly. `elementFormDefault="qualified"` makes your sub-elements have a namespace. When marshalling, JAXB needs to make this namespace present in the resulting XML. So it generates a namespace prefix like `ns2` and uses it in element names. You can customize this namespace prefix and even remove it forcing your namespace to be the default namespace. Changing namespace of subelements just to suppress `ns2` is not the right solution from my point of view. – lexicore Feb 14 '18 at 14:34
  • Aha, I get it now... You mean that by saying elementFormDefault="unqualified" I am messing up all namespaces of sub-elements and that's not correct thing to do. Got it, thanks. – peter.petrov Feb 14 '18 at 14:35
  • Ok, so it's `advertiser` that makes problems. Please post the code you use to marshal (including creation of the object instance you marshal). – lexicore Feb 14 '18 at 14:35
  • Yes, the top-level element is in lowercase for some reason. Done, added in question. – peter.petrov Feb 14 '18 at 14:36
  • "You can customize this namespace prefix and even remove it forcing your namespace to be the default namespace. " Seems that's exactly what I want yes, my namespace to be the default one. – peter.petrov Feb 14 '18 at 14:38
  • @peter.petrov See the update of the answer. As for the namespace prefixes, check [this answer](https://stackoverflow.com/questions/1982977/is-it-possible-to-customize-the-namespace-prefix-that-jaxb-uses-when-marshalling/1983172#1983172). You can configure a namespace prefix mapper. Also check the `@XmlSchema` annotation. – lexicore Feb 14 '18 at 14:45