|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Junior Member
Iscritto dal: Sep 2008
Messaggi: 8
|
[Java] Ordinamento di un file XML tramite Jdom
Salve!
Stò avendo problemi nel fare l'ordinamento di un file xml usando le librerie jdom. Questo è il codice che ho scritto: Codice PHP:
Bisogna focalizzarsi principalmente sulla parte dell'ordinamento (fatto tramite Bubble sort), quando inizia il ciclo While per intenderci. Il codice viene compilato (stranamente) senza problemi ma quando vado in esecuzione ho quest'errore: Exception in thread "AWT-EventQueue-0" org.jdom.IllegalAddException: The Content already has an existing parent "agenda" Quell'errore non mi è nuovo, l'ho già visto quando usavo il "agenda.addcontent" a sproposito.. ma stavolta pare sia diverso. Il problema infatti avviene al momento della scrittura del file, dopo aver ordinato il tutto. Commentando il codice di scrittura infatti non ci sono problemi di sorta. Ho provato anche a commentare la fase dello "scambio", ma il problema resta sempre lo stesso. Se commento tutto l'ordinamento non ci sono problemi. Insomma.. in teoria il problema è in quello che viene eseguito dentro il for ma non dentro l'if (c'è un solo for quindi non è difficile capire a quel mi riferisco :P ) ma non riesco proprio a capire cosa diavolo può essere. ps: stò scrivendo il tutto con netbeans e dopo aver fatto una GUI, quindi c'è un riferimento ad una casella, per l'appunto "casellasfoglia" Grazie, mi ci stò ammattendo :P |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Una delle caratteristiche interessanti di JDOM è che una lista di nodi non è rappresentata da classi specifiche e poco maneggevoli come NodeList per il DOM ma è gestita come una collezione java.util.List. E quindi è molto più pratica, intuitiva e maneggevole.
Con questo voglio dire che se devi solo scambiare 2 nodi nella lista, basta semplicemente scambiare i due oggetti nella lista, non scambiare tutti i nodi di testo contenuti nei nodi figli!!!! E non ti conviene nemmeno usare gli iteratori ... basterebbe sfruttare size() ed agire a livello di indici. E visto che la data è in un formato ben preciso e la usi diverse volte, ti conviene pure fare un metodo che converte la stringa in un Calendar o Date. Insomma ... con un po' di accortezza il codice verrebbe molto più pulito e almeno la metà in meno di quello che hai scritto.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
#3 |
|
Junior Member
Iscritto dal: Sep 2008
Messaggi: 8
|
Grazie mille per la risposta
Ecco, il problema è che non sono proprio un esperto di programmazione (ormai s'era capito) quindi anche volendo fare certe cose non saprei come farle :P Per invertire i 2 nodi l'idea iniziale era appunto di scambiarli tra di loro.. ma viste le difficoltà tecniche ho dovuto abbandonare e fare quest'altro metodo stupido, ma funzionante. Per questo vista la tua cortesia mi piacerebbe farti un paio di domande - Come faccio a sostituire solo il nodo? - Come faccio a "selezionare" l'elemento successivo senza l'uso di un iteratore? Grazie mille ancora |
|
|
|
|
|
#4 | |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Nota che si può sfruttare una cosa interessante di set() e cioè che ritorna l'elemento precedente!!! E questo permetterebbe di usare solo 1 get e 2 set e sopratutto senza usare variabili temporanee. Tecnica che è stata utilizzata da un metodo di java.util.Collections che è: public static void swap(List list, int i, int j) (solo da Java 1.4 in poi)
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
|
|
|
|
|
|
#5 | |
|
Junior Member
Iscritto dal: Sep 2008
Messaggi: 8
|
Quote:
Il metodo dei get() e set() è interessante, ma non riesco ad applicarlo al mio caso. Allora, il file xml che stò costruendo è strutturato così: <agenda> <appuntamento> <descrizione>compleanno</descrizione> <nome>pino</nome> <cognome>barba</cognome> <data>01/12/2008</data> <ora>00:00</ora> <priorita>Trascurabile</priorita> </appuntamento> </agenda> Io ho dichiarato come Element agenda, appuntamento e tutto il resto, dopodichè ho caricato dentro appuntamento i 6 campi (descrizione, nome etc) e l'ho fatto finchè non finivo di leggere dal file xml. Ogni volta che finivo a leggere quei 6 campi aggiungevo appuntamento ad agenda. Infine creo una lista chiamata "backup" nella quale colloco i vari appuntamenti appena caricati nell'agenda tramite la stringa: List backup = agenda.getChildren("appuntamento"); E fin qui tutto ok. Ora a me serve "ricacciare" da questo Element chiamato agenda la data del primo elemento, per confrontarla con quella del secondo e nel caso sostituirla. Se faccio backup.get(1) mi restituisce "[Element: <appuntamento/>]", ovviamente ho lo stesso output anche con backup.get(2). Andando un po' a logica ho provato a fare backup.get(1).getChildren("data") ma getChildren non compare tra i metodi disponibili (backup alla fine è cosa ben diversa da agenda quindi l'errore è motivato). Come faccio quindi a ricacciarmi la data? Una volta sorpassato questo scoglio penso di poter fare il resto Grazie ancora |
|
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Codice:
List appuntamenti = agenda.getChildren("appuntamento");
int size = appuntamenti.size();
for (int i = 0; i < size-1; i++) {
for (int j = i+1; j < size; j++) {
Element appuntamento1 = (Element) appuntamenti.get(i);
Element appuntamento2 = (Element) appuntamenti.get(j);
Calendar calendar1 = metodoPerParsingData(appuntamento1.getChildTextTrim("data"));
Calendar calendar2 = metodoPerParsingData(appuntamento2.getChildTextTrim("data"));
if (calendar1.after(calendar2)) {
appuntamenti.set(i, appuntamento2);
appuntamenti.set(j, appuntamento1);
}
}
}
Tutto qui .... quante righe sono??? Poche e ... pulite e chiare. Nota lo swap dei due elementi ... basta settare gli Element scambiando gli indici. P.S. il codice non l'ho provato, ovviamente. Ma in linea di massima dovrebbe essere ok.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) Ultima modifica di andbin : 25-09-2008 alle 10:07. |
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Prendo spunto dal tuo codice Andbin, per modificarlo di pochissimo in modo da renderlo un'implementazione dell'ordinamento Bubblesort, con l'aggiunta di un flag per interrompere l'algoritmo non appena la lista è ordinata (ovvero quando non ci sono più scambi in un'intera iterazione).
Codice:
List appuntamenti = agenda.getChildren("appuntamento");
int size = appuntamenti.size();
boolean flag = false;
while (size > 0)
{
if (flag)
{
break;
}
for (int i = 0; i < size-1; i++)
{
flag = true;
Element appuntamento1 = (Element) appuntamenti.get(i);
Element appuntamento2 = (Element) appuntamenti.get(i+1);
Calendar calendar1 = metodoPerParsingData(appuntamento1.getChildTextTrim("data"));
Calendar calendar2 = metodoPerParsingData(appuntamento2.getChildTextTrim("data"));
if (calendar1.after(calendar2))
{
appuntamenti.set(i, appuntamento2);
appuntamenti.set(i+1, appuntamento1);
flag = false;
}
}
size--;
}
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) Ultima modifica di banryu79 : 25-09-2008 alle 10:21. |
|
|
|
|
|
#8 |
|
Junior Member
Iscritto dal: Sep 2008
Messaggi: 8
|
Purtroppo non funziona, c'è lo stesso errore che avevo io
Ecco il codice che ho messo: Codice PHP:
Note: C:\Users\<mionome>\Documents\NetBeansProjects\Rubrica\src\calendario.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. Però il programma parte ugualmente. Quando provo a fare l'ordinamento esce lo stesso errore di prima, ovvero: Exception in thread "AWT-EventQueue-0" org.jdom.IllegalAddException: The Content already has an existing parent "agenda" Bloccandosi li.. non arriva neanche alla fase di scrittura dell'output edit: facendo 2 prove ho trovato cosa dà l'errore: backup.set(i, appuntamento2); backup.set(j, appuntamento1); Per trovarlo ho messo vari "System.out" in giro per il codice e si blocca sempre dopo aver eseguito quello prima di queste 2 istruzioni Ultima modifica di odiojava.net : 25-09-2008 alle 13:36. |
|
|
|
|
|
#9 | ||
|
Senior Member
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
|
Quote:
Il warning si potrebbe sopprimere ma comunque non te ne curare più di tanto (anche perché tra poco vedrai come risolvere senza fare dei set() su List). Quote:
Quando si setta o si aggiunge un elemento nella List fornita da JDOM, controlla che l'elemento non abbia già un parente. Ho anche provato a fare un detach() sul Element ma sembra non funzionare. Comunque una soluzione l'ho trovata: scambiare non gli elementi stessi ma il loro intero contenuto. E funziona. Dato un file XML: Codice:
<?xml version="1.0" encoding="ISO-8859-1"?> <agenda> <appuntamento><data>01/12/2008</data></appuntamento> <appuntamento><data>05/10/2007</data></appuntamento> <appuntamento><data>16/07/2008</data></appuntamento> <appuntamento><data>20/04/2008</data></appuntamento> </agenda> Codice:
import java.io.*;
import java.util.*;
import java.text.*;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.output.*;
import org.jdom.output.Format;
public class TestAgenda {
public static DateFormat df;
public static void main(String[] args) {
try {
df = new SimpleDateFormat("dd/MM/yyyy");
df.setLenient(false);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build("agenda.xml");
Element agenda = doc.getRootElement();
List appuntamenti = agenda.getChildren("appuntamento");
int size = appuntamenti.size();
for (int i = 0; i < size-1; i++) {
for (int j = i+1; j < size; j++) {
Element appuntamento1 = (Element) appuntamenti.get(i);
Element appuntamento2 = (Element) appuntamenti.get(j);
Calendar calendar1 = parseDate(appuntamento1.getChildTextTrim("data"));
Calendar calendar2 = parseDate(appuntamento2.getChildTextTrim("data"));
if (calendar1.after(calendar2)) {
List content1 = appuntamento1.removeContent();
List content2 = appuntamento2.removeContent();
appuntamento1.setContent(content2);
appuntamento2.setContent(content1);
}
}
}
XMLOutputter outputter = new XMLOutputter();
FileOutputStream output = new FileOutputStream("agenda_ord.xml");
outputter.output(doc, output);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Calendar parseDate (String s) throws ParseException {
Date d = df.parse(s);
Calendar c = Calendar.getInstance();
c.setTime(d);
return c;
}
}
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%) |
||
|
|
|
|
|
#10 |
|
Junior Member
Iscritto dal: Sep 2008
Messaggi: 8
|
Funziona così bene che stò per piangere dalla commozione
Grazie mille, finalmente il programma è sulla buona strada per essere completato ^_^ Ah visto che ci stò ne approfitto per chiedere una cosetta veloce Sapresti anche come "bloccare in scrittura" un determinato file tramite codice? In pratica vorrei che mentre il programma è in funzione non si possa modificare il file xml, per poi risbloccarlo ad esecuzione terminata. Cmq questa è una cosa superflua, la parte importante è fatta Grazie ancora ^__^ |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 06:10.



















