I'm going to simplify my classes and output as best I can here, but basically what I'm after is I want to add an org.w3c.dom.Element
(representing an atom link in this case) to a JAXB object I'm returning. The JAXB Class looks something like:
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import org.w3c.dom.Element;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "People", namespace = "main", propOrder = {
"any",
"persons"
})
public class People {
@XmlAnyElement
protected List<Element> any;
@XmlElement(name = "person", namespace = "main")
protected List<Person> persons;
[...]
}
I'm creating the Element using a template I create like this:
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
public class ElementGen {
public Element getTemplate() throws DOMException, SAXException, ParserConfigurationException {
final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = sf.newSchema(new StreamSource(
Thread.currentThread().getContextClassLoader().getResourceAsStream(ATOM_XSD)));
final DocumentBuilderFactory docBuilder = DocumentBuilderFactory.newInstance();
docBuilder.setSchema(schema);
final Document doc = docBuilder.newDocumentBuilder().newDocument();
linkTemplate = doc.createElementNS(ATOM_NAMESPACE, ATOM_LINK);
return linkTemplate;
}
}
(That's not actually what the class looks like, I'm just trying to make it as easy as possible to compile something to test it without all the external mess).
I then clone that template using linkTemplate.cloneNode(false);
Now this all works in that it returns xml, but the odd thing is that the xml I get back has additional namespaces attached:
<atom:link xmlns:ns3="main" xmlns="" href="href" rel="rel"/>
If I add linkTemplate.setAttribute("xmlns", null);
the "xmlns:ns3" namespace disappears and I get:
<atom:link xmlns="" href="href" rel="rel"/>
But there seems to be no way of removing that xmlns="". Am I creating the Element in the wrong way? Or perhaps something else is going wrong? I'm rather at a loss as to why it's adding these at all so any help/explanation would be appreciated.
Edit: I believe it must be related to the namespace of the document I use for generating the Element, but I'm not sure how to fix it. Is there any way of setting the (XML) targetNamespace on the document?
Edit 2: I'm not sure if it adds anything useful for anyone, but with more experimenting I found that linkTemplate.setAttribute("xmlns:" + anything, null);
has the effect of creating a link with xmlns:[anything]=""
and removing any others that would have otherwise been generated.
Edit 3: The relevant bits of the xsd used to generate the JAXB objects is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
xmlns="main"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:atom="http://www.w3.org/2005/Atom"
targetNamespace="main"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="People">
<xs:sequence>
<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="person" type="Person" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
[attributes]
</xs:complexType>
[other types etc.]