I have some questions about the processing in BaseStAXArtifactProcessor to write namespace prefixes. Let's start with this method:
protected void writeStart(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException { String prefix = writeElementPrefix(writer, uri); writeAttributePrefixes(writer, attrs); writer.writeStartElement(uri, name); if (prefix != null){ writer.writeNamespace(prefix,uri); } writeAttributes(writer, attrs); } writeAttributePrefixes calls down to XAttr.writePrefix. If the value is a QName then it calls writeQNamePrefix. private void writeQNamePrefix(XMLStreamWriter writer, QName qname) throws XMLStreamException { if (qname != null) { String prefix = qname.getPrefix(); String uri = qname.getNamespaceURI(); prefix = writer.getPrefix(uri); if (prefix != null) { return; } else { // Find an available prefix and bind it to the given URI NamespaceContext nsc = writer.getNamespaceContext(); for (int i=1; ; i++) { prefix = "ns" + i; if (nsc.getNamespaceURI(prefix) == null) { break; } } writer.setPrefix(prefix, uri); } } } If the QName has a uri which isn't yet bound to a prefix, this method binds it. Note that it does not write the namespace to the stream, nor does it return anything to its caller to tell it to write the namespace. So the resulting XML has an unbound prefix. writeQNamePrefix cannot write the namespace itself because it is being called before the element has been started. I think the processing needs to be changed to bubble up the prefix bindings back to writeStart, and then writeStart can write them. PolicyAttachPointProcessor.writePolicyPrefixes also goes through this code, so it would also have to be changed to return the prefix bindings to its callers (ConfiguredOperationProcessor, JavaImplementationProcessor). I gather that the reason the code is arranged this way is to minimize the number of prefixes generated by binding the prefix in the parent's element rather than the element we are about to write? Otherwise writeQNameValue could just write the namespace at the time the attribute value is being written. Speaking of writeQName value, I have a question about it too. private String writeQNameValue(XMLStreamWriter writer, QName qname) throws XMLStreamException { if (qname != null) { String prefix = qname.getPrefix(); String uri = qname.getNamespaceURI(); prefix = writer.getPrefix(uri); if (prefix != null && prefix.length() > 0) { // Use the prefix already bound to the given URI return prefix + ":" + qname.getLocalPart(); } else { // Find an available prefix and bind it to the given URI NamespaceContext nsc = writer.getNamespaceContext(); for (int i=1; ; i++) { prefix = "ns" + i; if (nsc.getNamespaceURI(prefix) == null) { break; } } writer.setPrefix(prefix, uri); writer.writeNamespace(prefix, uri); return prefix + ":" + qname.getLocalPart(); } } else { return null; } } I am wondering about the check for prefix.length() > 0. The documentation for getPrefix() is sketchy, but it seems to return the empty string if the given namespace is the default namespace. So this code generates a new prefix when the QName value uses the default namespace. Why does it do that? I think if getPrefix returns a non-null value of zero length, this method should return the local part of the QName with no prefix. Greg Dritschler