Espacio de nombre XML predeterminado, JDOM y XPath

Quiero usar JDOM para leer en un archivo XML, luego uso XPath para extraer datos del documento JDOM. Crea bien el objeto de documento, pero cuando uso XPath para consultar el documento para una lista de elementos, no obtengo nada.

Mi documento XML tiene un espacio de nombre predeterminado definido en el elemento raíz. Lo curioso es que cuando elimino el espacio de nombres predeterminado, ejecuta correctamente la consulta XPath y devuelve los elementos que quiero. ¿Qué más debo hacer para que mi consulta XPath devuelva resultados?

XML:

   Lord of the Rings: The Fellowship of the Ring 178 Ian Holm Elijah Wood Ian McKellen   The Matrix 136 Keanu Reeves Laurence Fishburne   

Java:

 public static void main(String args[]) throws Exception { SAXBuilder builder = new SAXBuilder(); Document d = builder.build("xpath.xml"); XPath xpath = XPath.newInstance("collection/dvd"); xpath.addNamespace(d.getRootElement().getNamespace()); System.out.println(xpath.selectNodes(d)); } 

XPath 1.0 no es compatible con el concepto de un espacio de nombres predeterminado ( XPath 2.0 lo hace). Cualquier etiqueta no prefijada siempre se supone que forma parte del espacio de nombre sin nombre.

Cuando usas XPath 1.0 necesitas algo como esto:

 public static void main(String args[]) throws Exception { SAXBuilder builder = new SAXBuilder(); Document d = builder.build("xpath.xml"); XPath xpath = XPath.newInstance("x:collection/x:dvd"); xpath.addNamespace("x", d.getRootElement().getNamespaceURI()); System.out.println(xpath.selectNodes(d)); } 

Tenía un problema similar, pero el mío era que tenía una mezcla de entradas XML, algunas de las cuales tenían un espacio de nombre definido y otras que no. Para simplificar mi problema, ejecuté el siguiente fragmento de JDOM después de cargar el documento.

 for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) { if (el.getNamespace() != null) el.setNamespace(null); } 

Después de eliminar todos los espacios de nombres, pude usar la navegación de estilo getChild (“elname”) simple o consultas XPath simples.

No recomendaría esta técnica como una solución general, pero en mi caso definitivamente fue útil.

También puedes hacer lo siguiente

/*[local-name() = 'collection']/*[local-name() = 'dvd']/

Aquí hay una lista de consultas xpath útiles.