PDA

View Full Version : leggere più valori con Xpath


dupa
01-05-2005, 17:13
Sto cercando di leggere dei dati con Xpath da un file xml.
Riesco a leggere il primo tag, invece poi se tento di leggerne un altro, mi dà eccezione :(

File xmlDocument = new File("c:/test.xml");
...
InputSource inputSource = new InputSource(new FileInputStream(xmlDocument));
...
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
...
int replication = Integer.parseInt(xPath.evaluate("/simulation/setup/replication", inputSource));
System.out.println(replication); // FUNZIONA!

warmuptime = Integer.parseInt(xPath.evaluate("/simulation/setup/warmuptime", inputSource));
System.out.println(warmuptime); // NON FUNZIONA!: mi dà javax.xml.xpath.XPathExpressionException

theClimber
01-05-2005, 17:27
Riesci a fare una prova di chiamata al metodo evaluate() usando un nodo DOM invece di un InputSource che si appoggia su uno stream?

Non vorrei che lo stream degli eventi sia stato consumato, per cui e' impossibile effettuare la seconda query....

Ciao

dupa
01-05-2005, 17:53
Riesci a fare una prova di chiamata al metodo evaluate() usando un nodo DOM invece di un InputSource che si appoggia su uno stream?

Non vorrei che lo stream degli eventi sia stato consumato, per cui e' impossibile effettuare la seconda query....

Ciao

immagino che probabilmente devo "resettarlo" ma se chiamo l'apposito metodo reset(), continuo ad avere problemi lo stesso.
Hai per caso un buon link a una guida per Xpath (su java) che possibilmente non si metta a parlare anche di Sax e Dom?

thanks

theClimber
01-05-2005, 18:41
Quando hai provato a fare il reset, quando hai effttuato il corrispondente mark()? E con che valore di limite di invalidazionde del mark? occhio che il valore e' in byte e che se viene superato il mark viene invalidato.

Non e' che il problema sia l'xpath stesso e che La classe Xpath che stai usando e' quella della JDK, che si basa pesantemente sulla API JAXP/TRAX. Di conseguenza DOM e SAX sono importanti.....

In alternativa potresti provare dom4j, e' un API per parsing XML che supporta anche xpath, piu' semplice da usare, comunque e' un .jar a parte e non e' uno standard.

Ma se inverti i 2 xpath, quello che legge warmuptime funziona?

dupa
01-05-2005, 20:38
Facendo così ora sembra andare:


File xmlDocument = new File("c:/test.xml");
InputSource inputSource;
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
try {
inputSource = new InputSource(new FileInputStream(xmlDocument));
replication = Integer.parseInt(xPath.evaluate("/simulator/setup/replication", inputSource));
System.out.println(replication);
inputSource = new InputSource(new FileInputStream(xmlDocument));
warmuptime = Integer.parseInt(xPath.evaluate("/simulator/setup/warmuptime", inputSource));
System.out.println(warmuptime);



in pratica continuo a ricaricare inputSource.
sicuramente non è la soluzione giusta al problema, per ora però mi accontento, se hai idee migliori son benvenute :D

Angus
02-05-2005, 08:29
Facendo così ora sembra andare:


File xmlDocument = new File("c:/test.xml");
InputSource inputSource;
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
try {
inputSource = new InputSource(new FileInputStream(xmlDocument));
replication = Integer.parseInt(xPath.evaluate("/simulator/setup/replication", inputSource));
System.out.println(replication);
inputSource = new InputSource(new FileInputStream(xmlDocument));
warmuptime = Integer.parseInt(xPath.evaluate("/simulator/setup/warmuptime", inputSource));
System.out.println(warmuptime);



in pratica continuo a ricaricare inputSource.
sicuramente non è la soluzione giusta al problema, per ora però mi accontento, se hai idee migliori son benvenute :D

Dalle API del java 1.5:


// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(new File("/widgets.xml"));

// evaluate the XPath expression against the Document
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget[@name='a']/@quantity";
Double quantity = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);

dupa
02-05-2005, 08:45
Dalle API del java 1.5:


// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(new File("/widgets.xml"));

// evaluate the XPath expression against the Document
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget[@name='a']/@quantity";
Double quantity = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);


Ciao, innanzitutto thanks.
Il codice da te postato ha l'aria di essere copia/incollato, potresti darmi il link da dove l'hai preso?
Un casino di Java, XML e XPath è che su internet si trovano un sacco di cose spesso troppo complesse rispetto le mie esigenze e spesso guide e codici che fanno rifermimento a vecchie versioni di Java dove venivano usate "librerie esterne" per elaborare i file .xml.

Comunque ero riuscito a far funzionare anche il mio codice con l'ultima versione, l'unico problema che aveva è che a ogni "evaluate" dell'xpath dovevo ri-definire l'inputsource con l'istruzione:

inputSource = new InputSource(new FileInputStream(xmlDocument));


In sostanza io vedo XPath come una sorta di SQL.
E vedo il file .xml come una sorta di database.

Vorrei quindi letto una volta il file .xml e definito come input poi poter fare interrogazioni tramite Xpath per estrarre in variabili le informazioni che mi servono

Angus
02-05-2005, 09:06
Ciao, innanzitutto thanks.
Il codice da te postato ha l'aria di essere copia/incollato, potresti darmi il link da dove l'hai preso?


Come dicevo nel mio post, dalle API java 1.5 (http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/xpath/package-summary.html)


Comunque ero riuscito a far funzionare anche il mio codice con l'ultima versione, l'unico problema che aveva è che a ogni "evaluate" dell'xpath dovevo ri-definire l'inputsource con l'istruzione:

inputSource = new InputSource(new FileInputStream(xmlDocument));


In sostanza io vedo XPath come una sorta di SQL.
E vedo il file .xml come una sorta di database.

Vorrei quindi letto una volta il file .xml e definito come input poi poter fare interrogazioni tramite Xpath per estrarre in variabili le informazioni che mi servono

Quel codice mostra un esempio di quello che diceva theClimber qualche post fa: costruire l'albero DOM del documento XML che hai e darlo in pasto alle espressioni XPath che vuoi. Se il codice ti risultasse poco esplicativo sono a disposizione per chiarimenti.

dupa
02-05-2005, 09:35
Come dicevo nel mio post, dalle API java 1.5 (http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/xpath/package-summary.html)



Quel codice mostra un esempio di quello che diceva theClimber qualche post fa: costruire l'albero DOM del documento XML che hai e darlo in pasto alle espressioni XPath che vuoi. Se il codice ti risultasse poco esplicativo sono a disposizione per chiarimenti.

Sì una domanda ce l'ho.
In pratica anche il mio codice funzionava per leggere il primo valore tramite XPath
Poi però per leggere il secondo valore mi toccava ricaricare l'inputsource.

Quindi ti domando, il tuo codice funzionerebbe direttamente così?? (per estrarre quantity1 e quantity2)


// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(new File("/widgets.xml"));

// evaluate the XPath expression against the Document
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget[@name='a']/@quantity1";
Double quantity1 = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);
String expression = "/widgets/widget[@name='a']/@quantity2";
Double quantity2 = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);


Oppure sarebbe necesasrio ogni volta che si estrae un valore andare a ri-parsare il file .xml e ri-creare l'oggetto Document?

thanks

Angus
02-05-2005, 09:45
Sì una domanda ce l'ho.
In pratica anche il mio codice funzionava per leggere il primo valore tramite XPath
Poi però per leggere il secondo valore mi toccava ricaricare l'inputsource.

Quindi ti domando, il tuo codice funzionerebbe direttamente così?? (per estrarre quantity1 e quantity2)

...

Oppure sarebbe necesasrio ogni volta che si estrae un valore andare a ri-parsare il file .xml e ri-creare l'oggetto Document?

thanks

L'albero DOM una volta creato è lì per qualsiasi (ri)utilizzo tu ne voglia fare. Unico limite è la dimensione del file XML, perchè l'albero DOM succhia parecchie risorse...
Ti confesso che questa tecnica non l'ho mai provata con XPath, ma da quello che conosco del framework java per XML ti dico: provare per credere (in fondo molto dipende anche dalla specifica implementazione del parser XML che utilizzi).

dupa
02-05-2005, 10:20
L'albero DOM una volta creato è lì per qualsiasi (ri)utilizzo tu ne voglia fare. Unico limite è la dimensione del file XML, perchè l'albero DOM succhia parecchie risorse...
Ti confesso che questa tecnica non l'ho mai provata con XPath, ma da quello che conosco del framework java per XML ti dico: provare per credere (in fondo molto dipende anche dalla specifica implementazione del parser XML che utilizzi).

Ok, ora sono in università stasera provo ste tecniche a casa e spero che vadano.
Comunque non ho necessità di prestazioni sul parsing dell'XML, mi basta solo leggere dei dati, elaborare e creare alla fine un XML con i risultati. la parte dove servirebbe efficienza è l'elaborazione, per il resto non ho problemi di prestazioni, e proprio per quello cerco la semplicità di programmazione (che xpath sembra offrire)

ciao

theClimber
02-05-2005, 13:01
Va bene usare xpath.

Se costruisci il document come nel pezzo di codice che ti ha postato Angus,
poi lo puoi usare nell'evaluate dell'xpath.

Alla fine il codice dovrebbe essere + o - questo (in neretto i cambiamenti rispetto al tuo codcie originale)


File xmlDocument = new File("c:/test.xml");
...
// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
org.w3c.Document document = builder.parse(xmlDocument);
...
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
...
int replication = Integer.parseInt(xPath.evaluate("/simulation/setup/replication", document));
System.out.println(replication); // FUNZIONA!

warmuptime = Integer.parseInt(xPath.evaluate("/simulation/setup/warmuptime", document));
System.out.println(warmuptime); // NON FUNZIONA!: mi dà javax.xml.xpath.XPathExpressionException

In questo modo il file lo processi una volta sola.

Ciao