Pagina 1 di 1

Parser XML Urgente!!!

Inviato: lun 19 nov 2007, 18:10
da Night_Watch
Ciao a tutti.

Ho un piccolo problema. Devono estrarre da un file XML il contenuto di due campi. Il linguaggio che devo usare è Java (sto provando con le API jdom + SAX ma non riesco). Il file XML è: http://www.nlm.nih.gov/databases/dtd/medline_sample.xml

I campi di cui devo estrarre il contenuto sono:

ArticleTitle
AbstractText

Grazie a tutti per l'aiuto.

Inviato: lun 19 nov 2007, 19:15
da stan
Il modo + veloce:

Codice: Seleziona tutto

import java.io.*;
import java.lang.*;
import java.util.*;
public class Prova{

public static void main(String[] args)throws IOException{
BufferedReader f=new BufferedReader(new FileReader("a.xml"));
String s=f.readLine();
StringTokenizer token;
 while(s!=null){
	if(s.startsWith("<ArticleTitle>")){
		System.out.println("Titolo:");
		System.out.println(s.substring(14, s.length()-15));
	}
	if(s.startsWith("<AbstractText>")){
		System.out.println("Abstract:");
		System.out.println(s.substring(14, s.length()-15));
	}
	s=f.readLine();
	}
	f.close();
 }
}
Controlla se e' giusto. L'ho buttato giu' in un paio di minuti.
Credo inoltre che se hai problemi di performance ti conviene usare la classe String.
Avevo letto dei benchmark tempo fa' in cui risultava + efficiente la classe String. Anche se per xml complessi e' meglio usare le classi apposite.

Inviato: lun 19 nov 2007, 19:29
da sir_alex
Per XML invece (necessita di java6 o in alternativa java5+stax):

Codice: Seleziona tutto

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

public class XmlExtractor
{
	private URL address=null;
	private ArrayList<Container> data=null;

	public XmlExtractor(String address) throws MalformedURLException
	{
		this.address=new URL(address);
		data=new ArrayList<Container>();
	}

	public static void main(String[] args)
	{
		try
		{
			XmlExtractor ext=new XmlExtractor("http://www.nlm.nih.gov/databases/dtd/medline_sample.xml");
			ext.parse();
			for(Object o: ext.getData())
				System.out.println(o);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	private ArrayList<Container> getData()
	{
		return data;
	}

	private void parse() throws IOException, XMLStreamException
	{
		Container c=null;
		String temp1=null, temp2=null;
		URLConnection conn=address.openConnection();
		InputStream in=conn.getInputStream();
		XMLStreamReader doc=XMLInputFactory.newInstance().createXMLStreamReader(in);
		for(int event=doc.next(); event!=XMLStreamConstants.END_DOCUMENT; event=doc.next())
		{
			switch(event)
			{
				case XMLStreamConstants.START_ELEMENT:
					temp1=doc.getLocalName();
					if("ArticleTitle".equals(temp1))
					{
						c=new Container();
					}
					break;
				case XMLStreamConstants.CHARACTERS:
					temp2=doc.getText();
					if("ArticleTitle".equals(temp1) && !"\n".equals(temp2))
					{
						c.setArticleTitle(temp2);
					}
					else if("AbstractText".equals(temp1) && !"\n".equals(temp2))
					{
						c.setArticleAbstract(temp2);
					}
					// else da non specificare
					break;
				case XMLStreamConstants.END_ELEMENT:
					if("AbstractText".equals(doc.getLocalName()))
					{
						data.add(c);
					}
					break;
				// default da non specificare
			}
		}
	}
	
	private static class Container
	{
		private String articleTitle=null;
		private String articleAbstract=null;
		
		public Container()
		{
		}

		public Container(String articleTitle, String articleAbstract)
		{
			this.articleTitle = articleTitle;
			this.articleAbstract = articleAbstract;
		}
		
		public String getArticleTitle()
		{
			return articleTitle;
		}
		public void setArticleTitle(String articleTitle)
		{
			this.articleTitle = articleTitle;
		}
		public String getArticleAbstract()
		{
			return articleAbstract;
		}
		public void setArticleAbstract(String articleAbstract)
		{
			this.articleAbstract = articleAbstract;
		}
		
		public String toString()
		{
			return "Title: "+articleTitle+"\nAbstract: "+articleAbstract;
		}
		
	}
}

Inviato: lun 19 nov 2007, 20:48
da Night_Watch
Grazie tanto per le risposte.

x stan:

Il codice non dà errori in compilazione ma il problema è che la linea viene letta come:

Codice: Seleziona tutto

<ArticleTitle>Transcription regulation of the nir gene cluster encoding nitrite reductase of Paracoccus denitrificans involves NNR and NirI, a novel type of membrane protein.</ArticleTitle>
e quindi non riesce a rilevare il tag <ArticleTitle> o gli altri. Di conseguenza gli if non sono mai veri.

x sir_alex:

Il file lo scarico in locale.

Ma con le API jdom non sarebbe più semplice??
Il mio problema è che non riesco a far funzionare bene l'iterator e non riesco ad accedere ai nodi più interni. Per chiarezza posto il codice che sto provando:

Codice: Seleziona tutto

public class MedlineParser {

	public static void main(String[] args) {
		Document documento = null;
		SAXBuilder saxBuilder = new SAXBuilder();

		 try
		 {
		   documento = saxBuilder.build(new File("C://medline/medsamp2007.xml")); 
				 
		   Element e = documento.getRootElement();
		   Iterator itr = e.getChild("MedlineCitation").getChildren("Article").iterator();
		  
		   int i=0;
		   while (itr.hasNext()) {
		   		i++;
		   		System.out.println("Elemento n°: " +i);
		   		e = (Element) itr.next();
		   		String title = e.getChildText("ArticleTitle");
		   		System.out.println(title);
		   		String abstracttext = e.getChildText("Abstract");		 	
		 			
		 	OperazioniDB inserimento = new OperazioniDB();
		 	inserimento.inserisci(title, abstracttext);
		   }
		 }
		 catch (NullPointerException exc) {
		 	exc.printStackTrace();
       }		 
		 catch (Exception exc){
		 	exc.printStackTrace();
		 }
	}
}
Questo codice mi estrae solo un elemento cioè il contenuto del primo ArticleTitle e poi basta.

Inviato: lun 19 nov 2007, 20:58
da stan
Night_Watch ha scritto:Grazie tanto per le risposte.

x stan:

Il codice non dà errori in compilazione ma il problema è che la linea viene letta come:

Codice: Seleziona tutto

<ArticleTitle>Transcription regulation of the nir gene cluster encoding nitrite reductase of Paracoccus denitrificans involves NNR and NirI, a novel type of membrane protein.</ArticleTitle>
e quindi non riesce a rilevare il tag <ArticleTitle> o gli altri. Di conseguenza gli if non sono mai veri.
Non ho capito che intendi.
Io ho provato a scaricare il file.xml (ho salvato il page source del link che ci hai passato).
Ho compilato e lanciato. Mi sembra ok. :roll:

Inviato: lun 19 nov 2007, 21:08
da Night_Watch
Scusami hai ragione funziona!!!

Il problema è che stavo provando con un altro XML che sembra strutturato nello stesso modo e non funziona!!! Come è possibile??

Il file XML in questione è:

http://www.nlm.nih.gov/databases/dtd/medsamp2007.xml

Inviato: lun 19 nov 2007, 21:24
da stan
Beh si,
ad esempio se fai :

Codice: Seleziona tutto

if(s.startsWith("<ArticleTitle>")){
      System.out.println("Titolo:");
        String a=s.substring(14, s.length()-15);
      System.out.println(a);
   }
Che poi e' quello scritto qua:
http://java.sun.com/docs/books/tutorial ... types.html
In Java puoi fare:

Codice: Seleziona tutto

 String myString="Questa e' una stringa interessantissima";
L'oggetto di tipo String probabilmente non puo' memorizzare stringhe troppo lunghe.
Forse e' quello il tuo problema? Beh, in quel caso, magari puoi creare una collezione di Stringhe (usando la classe Vector e la classe Iterator, con opportuni cast, memorizzi e recuperi sottostringhe).
Boh, comunque quello che ti ho postato prima a me funge...quindi non saprei...[/code]

Inviato: lun 19 nov 2007, 21:27
da stan
Night_Watch ha scritto:Scusami hai ragione funziona!!!

Il problema è che stavo provando con un altro XML che sembra strutturato nello stesso modo e non funziona!!! Come è possibile??

Il file XML in questione è:

http://www.nlm.nih.gov/databases/dtd/medsamp2007.xml
Credo non funzioni perche' questo xml e' indentato. ;)

Inviato: lun 19 nov 2007, 21:36
da Night_Watch
Grazie veramente tanto stan per l'aiuto. Sei stato grande!!! ;)
stan ha scritto:Credo non funzioni perche' questo xml e' indentato.
Avresti una soluzione a livello di codice??

Cioè si potrebbe adattare quello che mi hai passato per farlo funzionare anche con questo tipo di XML??

O comunque cambiarlo quando mi serve in base al tipo di XML?? Infatti mi serve solo perchè devo mettere il contenuto dei due campi in un database MySQL e quindi in base all'esigenza commento e decommento le linee di codice che mi servono.

Inviato: lun 19 nov 2007, 21:51
da stan
Beh,
la prima cosa che mi viene in mente e':
Da Konsole fai:

Codice: Seleziona tutto

grep "<ArticleTitle>" a.xml |head -1
e poi conti a mano gli spazi che precedono <ArticleTitle> (professionale eh? :lol: )
Una volta contati editi Prova.java.
Supponiamo che conti 8 spazi:
Allora Prova.java diventa da cosi':

Codice: Seleziona tutto

if(s.startsWith("<ArticleTitle>")){
      System.out.println("Titolo:");
        String a=s.substring(14, s.length()-15);
      System.out.println(a);
   }
a cosi':

Codice: Seleziona tutto

   if(s.startsWith("        <ArticleTitle>")){
      System.out.println("Titolo:");
        String a=s.substring(22, s.length()-15);
      System.out.println(a);
   }
come vedi ho aggiunto degli spazi (nell'esempio 8 ) al metodo startsWith.
Ho poi modificato l 1o param di substring(14+8=22).
Ricordarti di fare tutto quello che ti ho scritto qua sopra anche x <AbstractText>.
Poi ricompili e lanci.

Inviato: mar 20 nov 2007, 9:57
da sir_alex
Bè magari si fa prima, tra l'altro con DOM puoi fare il parsing dato che è un XML piccolo... c'è da dire che io nell'ultimo anno ho sempre usato SAX, quindi mi ricordo quello adesso come adesso!
La mia soluzione penso funzioni anche su XML simili, in fondo io cerco solo quei 2 tag, basta assicurarsi che venga prima il titolo dell'abstract! ;-)

Inviato: mar 20 nov 2007, 15:39
da Night_Watch
Ciao a tutti.

x sir_alex

Sapresti risolvere il mio problema modificando il pezzo di codice che ho postato in modo da usare SAX e JDOM??

Grazie.

Inviato: mar 20 nov 2007, 17:44
da sir_alex
Night_Watch ha scritto:Ciao a tutti.

x sir_alex

Sapresti risolvere il mio problema modificando il pezzo di codice che ho postato in modo da usare SAX e JDOM??

Grazie.
Stasera ci guardo per dom...

[edit] Ma perchè bisogna per forza usare un jar esterno? Ma usare le librerie standard nel jdk no? :-)

Inviato: mar 20 nov 2007, 22:19
da stan
Puoi anche prendere il mio codice e aggiungerci il codice per rimuovere l'indentazione.
Guarda le classi String e StringTokenizer.