Spazio dei nomi XML predefinito, JDOM e XPath

Voglio usare JDOM per leggere in un file XML, quindi utilizzare XPath per estrarre i dati dal documento JDOM. Crea l’object Document bene, ma quando uso XPath per interrogare il documento per un elenco di elementi, non ottengo nulla.

Il mio documento XML ha uno spazio dei nomi predefinito definito nell’elemento root. La cosa divertente è che quando rimuovo lo spazio dei nomi predefinito, esegue correttamente la query XPath e restituisce gli elementi che voglio. Cos’altro devo fare per ottenere la query XPath per restituire i risultati?

XML:

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

Giava:

 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 non supporta il concetto di spazio dei nomi predefinito (fa XPath 2.0 ). Si presume sempre che ogni tag non prefisso faccia parte dello spazio dei nomi senza nome.

Quando usi XPath 1.0 hai bisogno di qualcosa del genere:

 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)); } 

Ho avuto un problema simile, ma il mio era che avevo una combinazione di input XML, alcuni dei quali avevano uno spazio dei nomi definito e altri no. Per semplificare il mio problema ho eseguito il seguente snippet JDOM dopo aver caricato il documento.

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

Dopo aver rimosso tutti gli spazi dei nomi, sono stato in grado di utilizzare la semplice navigazione in stile getChild (“elname”) o semplici query XPath.

Non consiglierei questa tecnica come soluzione generale, ma nel mio caso è stata sicuramente utile.

Puoi anche fare quanto segue

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

Ecco la lista delle query utili di xpath.