2011-10-31 4 views
3

Actuellement, j'essaie de nettoyer un fichier HTML en utilisant JTidy, le convertir en XHTML et fournir les résultats à un analyseur DOM. Le code suivant est le résultat de ces efforts:Xerces DOM parser incroyablement lent?

public class HeaderBasedNewsProvider implements INewsProvider { 

    /* ... */ 

    public Collection<INewsEntry> getNewsEntries() throws NewsUnavailableException { 
      Document document; 
     try { 
      document = getCleanedDocument(); 
     } catch (Exception e) { 
      throw new NewsUnavailableException(e); 
     } 
     System.err.println(document.getDocumentElement().getTextContent()); 
     return null; 
    } 

    private final Document getCleanedDocument() throws IOException, SAXException, ParserConfigurationException { 
     InputStream input = inputStreamProvider.getInputStream(); 
     Tidy tidy = new Tidy(); 
     tidy.setXHTML(true); 
     ByteArrayOutputStream tidyOutputStream = new ByteArrayOutputStream(); 
     tidy.parse(input, tidyOutputStream); 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     factory.setValidating(false); 
     InputStream domInputStream = new ByteArrayInputStream(tidyOutputStream.toByteArray()); 
     System.err.println(factory.getClass()); 
     return factory.newDocumentBuilder().parse(domInputStream); 
    } 
} 

Cependant, l'implémentation de l'analyseur DOM (com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl) sur mon système semble être incroyablement lent. Même pour les documents d'une ligne telles que les suivantes, l'analyse syntaxique prend 2-3 minutes:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title></title></head><body><div class="text"><h2>Nachricht vom 16. Juni 2011</h2><h1>Titel</h1><p>Mitteilung <a href="dokumente/medienmitteilungen/MM_NR_jglp.pdf" target="_blank">weiter</a> mehr Mitteilung</p></div></body></html> 

Notez que - contrairement à l'analyseur DOM - JTidy termine ses travaux dans une seconde. Par conséquent, je soupçonne que je suis en quelque sorte abusant de l'API DOM.

Merci d'avance pour toute suggestion sur celui-ci!

+0

Très étrange. Ça ne devrait pas être aussi lent que ça sur un si petit document. Et puisque vous définissez explicitement la validation sur false, je ne m'attendrais pas à ce qu'il résolve les problèmes de la DTD. Pouvez-vous passer cela à travers un profiler pour savoir quels appels prennent le plus de temps? –

Répondre

7

Même s'il n'est pas validé, un analyseur XML doit extraire la DTD, par exemple pour prendre en charge les entités de caractères nommées. Vous devriez envisager de mettre en œuvre un EntityResolver qui résout la demande de la DTD pour une copie locale.

+1

C'est le problème ... J'ai exécuté le code via un profileur et 98,9% du temps d'exécution (120 secondes) a été passé dans 'java.net.SocketInputStream.read'. Cela provient à son tour d'un 'HttpURLConnection' qui est créé par un' XMLDTDScannerImpl' de l'analyseur Xerces interne du JRE. Même si la validation DTD standard est désactivée, il faudra toujours ces déclarations d'entité. Je n'ai jamais utilisé la DTD moi-même (schémas toujours disponibles localement). +1 –

+1

Votre suggestion est correcte, je viens de le vérifier dans mon exemple. Pour des raisons de commodité, Xerces permet de désactiver la récupération de la DTD en utilisant un paramètre: 'factory.setFeature (" http://apache.org/xml/features/nonvalidating/load-external-dtd ", false);' Merci pour l'aide rapide! –

+0

Voir http://xerces.apache.org/xerces2-j/features.html pour les autres fonctionnalités disponibles. – PypeBros

2

HTML dtd sont énormes, en utilisant des inclusions. Ils prennent pour toujours. Utilisez un XML catalog. Là on peut stocker les dtds localement et les mapper par leur identification de système.

Si vous utilisez un outil, comme Maven, vous trouverez suffisamment de pointeurs.

L'avantage i.o. interceptant des entités comme la réponse acceptée suggère, c'est que vous recevez les caractères corrects.