2009-10-15 10 views
5

Używam Java (6) XML-Api do zastosowania transformacji xslt na dokumencie HTML z Internetu. Ten dokument jest dobrze sformułowany xhtml i dlatego zawiera poprawną specyfikację DTD (<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">). Teraz pojawia się problem: Transformacja Uppon Procesor XSLT próbuje pobrać DTD, a serwer W3 zaprzecza temu przez błąd HTTP 503 (z powodu Bandwith Limitation wg w3).Java, xml, XSLT: zapobiegaj walidacji DTD

Jak mogę zapobiec procesowi pobierania dtd przez procesor XSLT? Nie potrzebuję zatwierdzonego mojego dokumentu wejściowego.

źródłowy jest:

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(); 
    } 

czytam następujące quesitons tutaj na SO, ale wszystkie one użyć innego XML API:

Dzięki!

Odpowiedz

5

Niedawno miałem ten problem podczas unmarshalling XML przy użyciu JAXB. Odpowiedzią było utworzenie źródła SAX ze źródła XmlReader i InputSource, a następnie przekazanie go do metody unmarshal() JAXB UnMarshaller. Aby uniknąć ładowania zewnętrznego DTD, ustawiłem niestandardowy EntityResolver na 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); 

Jak napisano, zwyczaj ten podmiot nazw będzie wyjątek, jeśli kiedykolwiek poprosił, aby rozwiązać podmiot inny niż ten, który chcesz go rozwiązać. Jeśli chcesz, aby to było dalej i załaduj zdalny obiekt, usuń linię "throws".

+1

Na wypadek, gdyby ktoś miał te same problemy: To prowadzi do właściwego kierunku (to dlatego przyjąłem odpowiedź). Jeśli nie chcesz zwrócić DTD, możesz również zwrócić pusty. – theomega

+1

Proszę poprawić wielkość liter: "XmlReader" powinien być "XMLReader" – wau

-1

Musisz być przy użyciu 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

Dzięki za odpowiedź, ale ten kod faktycznie zgłasza ten sam wyjątek: 'java.io.IOException: Serwer zwrócił kod odpowiedzi HTTP: 503 dla adresu URL: http: // www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' Musisz zmienić' src.getByteStream() 'do' src' w linii 5, aby uzyskać działanie w ogóle, ale wciąż jest ten sam wyjątek. – theomega

+1

To nic nie zmienia. Możesz przeanalizować dokument podczas transformacji ze źródła strumienia, przed transformacją do DOMSource, ale w przeciwnym razie wystąpi brakujący wyjątek DTD.To "rozwiązanie" niczego nie rozwiązuje, a jedynie wprowadza w błąd. – mvmn

3

Spróbuj ustawić funkcję w swojej 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); 

Teraz jestem przeżywa te same problemy wewnątrz XSLT (2), gdy wywołanie funkcji do analizy dokumentów zewnętrznych XHTML stron.

0

jeśli używasz

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 

można spróbować wyłączyć sprawdzanie DTD kodu fllowing:

dbf.setValidating(false); 
+0

Zobacz odpowiedź od Chrisa, to jest dokładnie to samo. – theomega

2

Dotychczasowe odpowiedzi doprowadziły mnie do rozwiązania, ale to nie było oczywiste dla mnie tak tutaj jest kompletny:

private void convert(InputStream xsltInputStream, InputStream srcInputStream, OutputStream destOutputStream) throws SAXException, ParserConfigurationException, 
     TransformerFactoryConfigurationError, TransformerException, IOException { 
    //create a parser with a fake entity resolver to disable DTD download and validation 
    XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); 
    xmlReader.setEntityResolver(new EntityResolver() { 
     public InputSource resolveEntity(String pid, String sid) throws SAXException { 
      return new InputSource(new ByteArrayInputStream(new byte[] {})); 
     } 
    }); 
    //create the transformer 
    Source xsltSource = new StreamSource(xsltInputStream); 
    Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource); 
    //create the source for the XML document which uses the reader with fake entity resolver 
    Source xmlSource = new SAXSource(xmlReader, new InputSource(srcInputStream)); 
    transformer.transform(xmlSource, new StreamResult(destOutputStream)); 
} 
Powiązane problemy