JAXB Unable To Handle Attribute with Colon (:) in name?
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 开发者_如何学Pythonthe 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""
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.
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.
精彩评论