Domanda

Voglio usare JDOM per leggere in un file XML, quindi utilizzare XPath per estrarre i dati dal documento JDOM. Si crea l'oggetto multa documento, ma quando uso XPath per interrogare il documento per un elenco di elementi, non ottengo niente.

Il documento XML ha un namespace di default definito l'elemento radice. La cosa divertente è, quando rimuovo il namespace di default, viene eseguito con successo la query XPath e restituisce gli elementi che voglio. Che altro devo fare per ottenere la mia query XPath per restituire i risultati?

XML:

<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.foo.com">
<dvd id="A">
  <title>Lord of the Rings: The Fellowship of the Ring</title>
  <length>178</length>
  <actor>Ian Holm</actor>
  <actor>Elijah Wood</actor>
  <actor>Ian McKellen</actor>
</dvd>
<dvd id="B">
  <title>The Matrix</title>
  <length>136</length>
  <actor>Keanu Reeves</actor>
  <actor>Laurence Fishburne</actor>
</dvd>
</collection>

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));
}
È stato utile?

Soluzione

XPath 1.0 non supporta il concetto di uno spazio dei nomi di default ( XPath 2.0 fa).  Ogni tag senza prefisso è sempre assunto a far parte della no-nome del namespace.

Quando si utilizza XPath 1.0 è necessario qualcosa di simile:

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

Altri suggerimenti

Ho avuto un problema simile, ma la mia era che avevo una miscela di input XML, alcune delle quali aveva un namespace definito e altri che non hanno. Per semplificare il mio problema ho eseguito il seguente frammento JDOM dopo il caricamento del 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 semplice getChild ( "elname") di navigazione stile o semplici XPath query.

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

È anche possibile effettuare le seguenti

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

Ecco la lista dei query utile XPath.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top