JAXB Unable To Handle Attribute with Colon (:) in name?
Asked Answered
U

2

8

I am attempting to use JAXB to unmarshall an XML files whose schema is defined by a DTD (ugh!).

The external provider of the DTD has specified one of the element attributes as xml:lang:

<!ATTLIST langSet
id ID #IMPLIED
xml:lang CDATA #REQUIRED
>

This comes into the xjc-generated class (standard generation; no *.xjb magic) as:

@XmlAttribute(name = "xml:lang", required = true)
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String xmlLang;

However, when unmarshalling valid XML files with JAXB, the xmlLang attribute is always null.

When I edited the XML file, replacing xml:lang with lang and changed the @XmlAttribute to match, unmarshalling was successful (i.e. attributes were non-null).

I did find this http://old.nabble.com/unmarshalling-ignores-element-attribute-%27xml%27-td22558466.html. But, the resolution there was to convert to XML Schema, etc. My strong preference is to go straight from an un-altered DTD (since it is externally provided and defined by an ISO standard).

Is this a JAXB bug? Am I missing something about "namespaces" in attribute names?

FWIW, java -version = "build 1.6.0_20-b02" and xjc -version = "xjc version "JAXB 2.1.10 in JDK 6""

Unlive answered 9/6, 2010 at 13:45 Comment(3)
Which DTD is this? xml:lang is an XML Schema meta-attribute, so the DTD is describing something that originated from a Schema, which would suggest to me that there's a full schema out there.Physiology
AFAIK, the publisher only makes a DTD available. It would hard to image that they publish a DTD based on an Schema but don't make the latter available. However, I've had the author of some related tools ask me if I'm using a Schema to generate the JAXB objects, so there might be something out there...Unlive
Thanks for the nabble link. You made my life easier.Pacian
U
7

Solved the issue by changing replacing xml: with a namespace declaration in the JAXB-generated class:

@XmlAttribute(name = "lang", namespace="http://www.w3.org/XML/1998/namespace", required = true)

Which makes sense, in a way.

Without this kind of guidance, how would JAXB know how to interpret the otherwise-undefined namespace xml:? Unless, of course, it implemented some special-case internal handling to xml: as done in http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamReader.html#getNamespaceURI%28java.lang.String%29 (see the first NOTE:)

Whether it's a bug in xjc's generation of the annotated objects or a bug in the unmarhaller, or simply requires a mapping somewhere in the xjc process is still an open question in my mind.

For now, it's working and all it requires is a little xjc magic, so I'm reasonably happy.

Unlive answered 10/6, 2010 at 18:34 Comment(1)
Awesome, it took me hours of research! :DPentothal
S
1

Disclaimer: Although 8 years late, I am adding this answer for lost souls such as myself trying to understand auto generation of java files from a DTD.

You can set project wide namespaces for the unmarshaller to work with directly in the project-info.java file via the @XmlSchema option.

This file should be automatically generated by xjc when generating classes from a schema, however it appears xjc does not automatically generate the package-info.java file when generating from a DTD!

However, you can manually make this file, and add it to the same package as the files generated by xjc.

The file would look like the following:

package-info.java :

@XmlSchema(
    elementFormDefault=XmlNsForm.QUALIFIED, 
    xmlns = {
            @XmlNs(prefix="xlink", namespaceURI="http://www.w3c.org/1999/xlink"),
            @XmlNs(prefix="namespace2", namespaceURI="http://www.w3c.org/1999/namespace2")
    }) 

package your.generated.package.hierarchy;
import javax.xml.bind.annotation.*;

You can add as many namespaces as required, simply add a new line in the form:

@XmlNs(prefix="namespace", namespaceURI="http://www.uri.to.namespace.com")

The benefit of doing it this way, rather than compared to editing the generated @XmlAttribute is that you do not need to change each generated XmlAttribute, and you do not need to manually remove the namespaces from the XmlAttribute name variable.

Sheathing answered 21/6, 2018 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.