2009-10-15 15 views
5

J'utilise Java (6) XML-Api pour appliquer une transformation xslt sur un document html à partir du Web. Ce document est bien formaté xhtml et contient donc un DTD-Spec valide (<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">). Maintenant, un problème survient: La transformation Uppon du processeur XSLT essaie de télécharger la DTD et le serveur w3 refuse cela par une erreur HTTP 503 (due à Bandwith Limitation par w3).Java, xml, XSLT: Empêcher la validation DTD

Comment puis-je empêcher le processeur XSLT de télécharger le dtd? Je n'ai pas besoin de mon document d'entrée validé.

Source est:

import javax.xml.transform.Source; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 

-

String xslt = "<?xml version=\"1.0\"?>"+ 
    "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">"+ 
    " <xsl:output method=\"text\" />"+   
    " <xsl:template match=\"//html/body//div[@id='bodyContent']/p[1]\"> "+ 
    "  <xsl:value-of select=\".\" />"+ 
    "  </xsl:template>"+ 
    "  <xsl:template match=\"text()\" />"+ 
    "</xsl:stylesheet>"; 

    try { 
    Source xmlSource = new StreamSource("http://de.wikipedia.org/wiki/Right_Livelihood_Award"); 
    Source xsltSource = new StreamSource(new StringReader(xslt)); 
    TransformerFactory ft = TransformerFactory.newInstance(); 

    Transformer trans = ft.newTransformer(xsltSource); 

    trans.transform(xmlSource, new StreamResult(System.out)); 
    } 
    catch (Exception e) { 
    e.printStackTrace(); 
    } 

Je lis les quesitons suivants ici sur le SO, mais ils utilisent tous une autre XML Api:

Merci!

Répondre

5

J'ai eu récemment cette question en unmarshalling XML en utilisant JAXB. La réponse consistait à créer une source SAX à partir d'un XmlReader et d'InputSource, puis à la transmettre à la méthode unmarshal() de JAXB UnMarshaller. Pour éviter de charger la DTD externe, j'ai défini un EntityResolver personnalisé sur XmlReader.

SAXParserFactory spf = SAXParserFactory.newInstance(); 
SAXParser sp = spf.newSAXParser(); 
XMLReader xmlr = sp.getXMLReader(); 
xmlr.setEntityResolver(new EntityResolver() { 
    public InputSource resolveEntity(String pid, String sid) throws SAXException { 
     if (sid.equals("your remote dtd url here")) 
      return new InputSource(new StringReader("actual contents of remote dtd")); 
     throw new SAXException("unable to resolve remote entity, sid = " + sid); 
    } }); 
SAXSource ss = new SAXSource(xmlr, myInputSource); 

Comme écrit, ce résolveur entité personnalisée lancera une exception si elle a jamais demandé de résoudre une entité autre que celui que vous voulez résoudre. Si vous voulez simplement que l'on poursuive et charger l'entité distante, supprimez la ligne "throws".

+1

Juste au cas où quelqu'un a les mêmes problèmes: Cela conduit dans la bonne direction (c'est pourquoi j'ai accepté la réponse). Si vous ne voulez pas renvoyer la DTD, vous pouvez également retourner une DTD vide. – theomega

+1

Veuillez corriger la capitalisation: 'XmlReader' devrait être 'XMLReader' – wau

-1

Vous devez utiliser javax.xml.parsers.DocumentBuilderFactory

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setValidating(false); 
DocumentBuilder builder = factory.newDocumentBuilder(); 
InputSource src = new InputSource("http://de.wikipedia.org/wiki/Right_Livelihood_Award") 
Document xmlDocument = builder.parse(src.getByteStream()); 
DOMSource source = new DOMSource(xmlDocument); 
TransformerFactory tf = TransformerFactory.newInstance(); 
Transformer transformer = tf.newTransformer(xsltSource); 
transformer.transform(source, new StreamResult(System.out)); 
+0

Merci pour la réponse, mais ce code jette effectivement la même exception: 'java.io.IOException: le serveur a renvoyé le code de réponse HTTP: 503 pour l'URL: http: // www.w3.org/TR/xhtml1/DTD/xhtml1-transitionnel.dtd' Vous devez changer le' src.getByteStream() 'à' src' dans la ligne 5 pour que cela fonctionne, mais il y a toujours la même exception. – theomega

+1

Cela ne change rien. Vous pouvez analyser le document lors de la transformation à partir de la source du flux, avant la transformation en DOMSource, mais une exception DTD dans les deux cas manquera.Donc cette "solution" ne résout rien, et ne trompe que. – mvmn

3

essayez de définir une fonction dans votre DocumentBuilderFactory:

URL url = new URL(urlString); 
InputStream is = url.openStream(); 
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 
DocumentBuilder db; 
db = dbf.newDocumentBuilder(); 
Document result = db.parse(is); 

En ce moment, je rencontre les mêmes problèmes à l'intérieur XSLT (2) lorsque vous appelez la fonction de documents pour analyser XHTML pages externes.

0

si vous utilisez

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 

vous pouvez essayer de désactiver la validation dtd avec le code fllowing:

dbf.setValidating(false); 
+0

Voir la réponse de Chris, c'est exactement pareil. – theomega

2

Les réponses précédentes m'a conduit à une solution, mais est était pas évident pour moi si en voici un complet:

Questions connexes