//We'll use some reflection to grab the known namespaces from woodstox
//or the xerces parser and fake extra namespace decls on the root elements.
//slight performance penalty, but there already is a penalty if you are validating
//anyway.
NamespaceContext c = source.getNamespaceContext();
final Map<String, String> nsMap = new TreeMap<String, String>();
try {
if (c instanceof W3CNamespaceContext) {
Element element = ((W3CNamespaceContext)c).getElement();
while (element != null) {
NamedNodeMap namedNodeMap = element.getAttributes();
for (int i = 0; i < namedNodeMap.getLength(); i++) {
Attr attr = (Attr)namedNodeMap.item(i);
if (attr.getPrefix() != null && attr.getPrefix().equals("xmlns")) {
nsMap.put(attr.getLocalName(), attr.getValue());
}
}
element = (Element)element.getParentNode();
}
} else {
try {
//Woodstox version
c = (NamespaceContext)c.getClass().getMethod("createNonTransientNsContext",
Location.class)
.invoke(c, new Object[1]);
} catch (Throwable t) {
//ignore
}
Field f = ReflectionUtil.getDeclaredField(c.getClass(), "mNamespaces");
f.setAccessible(true);
String ns[] = (String[])f.get(c);
for (int x = 0; x < ns.length; x += 2) {
nsMap.put(ns[x], ns[x + 1]);
}
}
} catch (Throwable t) {
//internal JDK/xerces version
try {
Field f = ReflectionUtil.getDeclaredField(c.getClass(), "fNamespaceContext");
f.setAccessible(true);
Object c2 = f.get(c);
Enumeration enm = (Enumeration)c2.getClass().getMethod("getAllPrefixes").invoke(c2);
while (enm.hasMoreElements()) {
String s = (String)enm.nextElement();
if (s == null) {
nsMap.put("", c.getNamespaceURI(s));
} else {
nsMap.put(s, c.getNamespaceURI(s));
}
}
} catch (Throwable t2) {
//ignore
}