public static void removeUnusedNamespaces(Document document) {

		final Set<String> namespaces = new HashSet<String>();

		document.normalizeDocument();

		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 attribute = attributes.item(i);

					if (XML_NAMESPACE.equals(attribute.getNamespaceURI())) {
						continue;
					}

					String prefix;

					if (XML_SCHEMA_INSTANCE.equals(attribute.getNamespaceURI())) {
						if ("type".equals(attribute.getLocalName())) {
							String value = attribute.getNodeValue();

							if (value.contains(":")) {
								prefix = value.substring(0, value.indexOf(":"));
							} else {
								prefix = null;
							}
						} else {
							continue;
						}
					} else {
						String value = attribute.getNodeValue();

						if (value.contains(":")) {
							prefix = value.substring(0, value.indexOf(":"));
						} else {
							prefix = attribute.getPrefix();
						}
					}

					namespace = element.lookupNamespaceURI(prefix);

					if (namespace == null) {
						continue;
					}

					namespaces.add(namespace);
				}
			}
		});

		traverse(element, new ElementVisitor() {

			public void visit(Element element) {

				Set<String> removeLocalNames = new HashSet<String>();

				NamedNodeMap attributes = element.getAttributes();

				for (int i = 0; i < attributes.getLength(); i++) {
					Node attribute = attributes.item(i);

					if (!XML_NAMESPACE.equals(attribute.getNamespaceURI())) {
						continue;
					}

					if (namespaces.contains(attribute.getNodeValue())) {
						continue;
					}

					removeLocalNames.add(attribute.getLocalName());
				}

				for (String localName : removeLocalNames) {
					element.removeAttributeNS(XML_NAMESPACE, localName);
				}
			}
		});
	}
public static void removeUnusedNamespaces ( Document document ) { final Set < String > namespaces = new HashSet < String > ( ) ; document . normalizeDocument ( ) ; 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 attribute = attributes . item ( i ) ; if ( XML_NAMESPACE . equals ( attribute . getNamespaceURI ( ) ) ) { continue ; } String prefix ; if ( XML_SCHEMA_INSTANCE . equals ( attribute . getNamespaceURI ( ) ) ) { if ( "type" . equals ( attribute . getLocalName ( ) ) ) { String value = attribute . getNodeValue ( ) ; if ( value . contains ( ":" ) ) { prefix = value . substring ( 0 , value . indexOf ( ":" ) ) ; } else { prefix = null ; } } else { continue ; } } else { String value = attribute . getNodeValue ( ) ; if ( value . contains ( ":" ) ) { prefix = value . substring ( 0 , value . indexOf ( ":" ) ) ; } else { prefix = attribute . getPrefix ( ) ; } } namespace = element . lookupNamespaceURI ( prefix ) ; if ( namespace == null ) { continue ; } namespaces . add ( namespace ) ; } } } ) ; traverse ( element , new ElementVisitor ( ) { public void visit ( Element element ) { Set < String > removeLocalNames = new HashSet < String > ( ) ; NamedNodeMap attributes = element . getAttributes ( ) ; for ( int i = 0 ; i < attributes . getLength ( ) ; i ++ ) { Node attribute = attributes . item ( i ) ; if ( ! XML_NAMESPACE . equals ( attribute . getNamespaceURI ( ) ) ) { continue ; } if ( namespaces . contains ( attribute . getNodeValue ( ) ) ) { continue ; } removeLocalNames . add ( attribute . getLocalName ( ) ) ; } for ( String localName : removeLocalNames ) { element . removeAttributeNS ( XML_NAMESPACE , localName ) ; } } } ) ; }
JAXB adds all namespaces known by the JAXBContext to the root element of
the XML document for performance reasons as per JAXB-103
(http://java.net/
jira/browse/JAXB-103?focusedCommentId=64411&page=com.atlassian
.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_64411).

This helper method based on Reboot's
(http://stackoverflow.com/users/392730/reboot) response to a
stackoverflow question on the subject. I've modified it slightly, but it
will prune down the namespaces to only those used.

@param document
Document object representing the entire XML document