Controlling namespace prefixes in JAXB

前端 未结 5 777
无人及你
无人及你 2020-12-03 12:05

How does jaxb determine the list of namespace prefix declarations whem marshalling an object? I used xjc to compile java classes for ebics (ebics schema). When I create an i

5条回答
  •  温柔的废话
    2020-12-03 13:00

    JAXB always adds all namespaces that are known by the JAXBContext to the root element of the XML document for performance reasons. See this comment by Kohsuke on JAXB-103 for more information.

    The only way I found to deal with this, is to traverse the document myself after it has been created with JAXB and remove all unused namespaces using the following helper class:

    public class RemoveUnusedNamespaces {
    
        private static final String XML_NAMESPACE_SCHEMA_INSTANCE = "http://www.w3.org/2001/XMLSchema-instance";
    
        private static final String XML_NAMESPACE_NAMESPACE = "http://www.w3.org/2000/xmlns/";
    
        private interface ElementVisitor {
    
            void visit(Element element);
    
        }
    
        public void process(Document document) {
            final Set namespaces = new HashSet();
    
            Element element = document.getDocumentElement();
            traverse(element, new ElementVisitor() {
    
                public void visit(Element element) {
                    String namespace = element.getNamespaceURI();
                    if (namespace == null)
                        namespace = "";
                    namespaces.add(namespace);
                    NamedNodeMap attributes = element.getAttributes();
                    for (int i = 0; i < attributes.getLength(); i++) {
                        Node node = attributes.item(i);
                        if (XML_NAMESPACE_NAMESPACE.equals(node.getNamespaceURI()))
                            continue;
                        String prefix;
                        if (XML_NAMESPACE_SCHEMA_INSTANCE.equals(node.getNamespaceURI())) {
                            if ("type".equals(node.getLocalName())) {
                                String value = node.getNodeValue();
                                if (value.contains(":"))
                                    prefix = value.substring(0, value.indexOf(":"));
                                else
                                    prefix = null;
                            } else {
                                continue;
                            }
                        } else {
                            prefix = node.getPrefix();
                        }
                        namespace = element.lookupNamespaceURI(prefix);
                        if (namespace == null)
                            namespace = "";
                        namespaces.add(namespace);
                    }
                }
    
            });
            traverse(element, new ElementVisitor() {
    
                public void visit(Element element) {
                    Set removeLocalNames = new HashSet();
                    NamedNodeMap attributes = element.getAttributes();
                    for (int i = 0; i < attributes.getLength(); i++) {
                        Node node = attributes.item(i);
                        if (!XML_NAMESPACE_NAMESPACE.equals(node.getNamespaceURI()))
                            continue;
                        if (namespaces.contains(node.getNodeValue()))
                            continue;
                        removeLocalNames.add(node.getLocalName());
                    }
                    for (String localName : removeLocalNames)
                        element.removeAttributeNS(XML_NAMESPACE_NAMESPACE, localName);
                }
    
            });
        }
    
        private final void traverse(Element element, ElementVisitor visitor) {
            visitor.visit(element);
            NodeList children = element.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                Node node = children.item(i);
                if (node.getNodeType() != Node.ELEMENT_NODE)
                    continue;
                traverse((Element) node, visitor);
            }
        }
    
    }
    

提交回复
热议问题