2009-10-15 15 views
5

Web'den bir html belgesine xslt dönüşümü uygulamak için Java (6) XML-Api'yi kullanıyorum. Bu belge iyi biçimlendirilmiş xhtml'dir ve bu nedenle geçerli bir DTD-Spec (<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">) içerir. Şimdi bir sorun oluştu: Uppon transformasyonu, XSLT-İşlemcinin DTD'yi indirmeyi denediğini ve w3-sunucusunun bunu bir HTTP 503 hatasıyla reddettiğini (Bandwith Limitation w3 ile) reddediyor.Java, xml, XSLT: DTD Doğrulamasını Önleme

XSLT İşlemcisinin dtd dosyasını nasıl indirmesini engelleyebilirim? Giriş dokümanımın onaylanmış olmasına gerek yok.

Kaynak:

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; 

- Ben burada SO aşağıdaki quesitons okumak

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

, ama hepsi başka bir XML-Api kullanın:

Teşekkürler!

cevap

5

kullanıyor olmanız gerekir. Cevap, bir XmlReader ve InputSource'dan bir SAXSource oluşturmak, ardından bunu JAXB UnMarshaller'in unmarshal() yöntemine iletmekti. Harici DTD'yi yüklemekten kaçınmak için XmlReader'da özel bir EntityResolver ayarlıyorum. Her zamankinden bunu çözmek istiyoruz olandan DİĞER bir varlık çözmek istedi eğer

yazılı olarak
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); 

, bu özel varlık çözümleyici bir özel durum oluşturur. Sadece devam etmesini ve uzak nesneyi yüklemesini istiyorsanız, "atma" çizgisini kaldırın. senin DocumentBuilderFactory bir özelliği ayarı

+1

Sadece birisinin aynı sorunları varsa: Bu doğru yöne doğru yol alır (bu yüzden cevabı kabul ettim). DTD'yi iade etmek istemiyorsanız, boş bir tane de döndürebilirsiniz. – theomega

+1

Lütfen büyük harf yazımı düzeltin: 'XmlReader', 'XMLReader' olmalıdır – wau

-1

Sen JAXB kullanarak XML unmarshalling ederken Geçenlerde bu sorunu vardı 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

Cevabınız için teşekkürler, ancak bu kod aslında şu istisnayı atar: 'java.io.IOException: Sunucu HTTP yanıt kodunu döndürdü: URL için 503: http: // www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ' ' src.getByteStream 'i değiştirmeniz gerekiyor (5) 'de "src" yi çalistirmak için calistiriyorum ama hala ayni istisna var. – theomega

+1

Bu hiçbir şeyi değiştirmez. Aktarım kaynağından, dönüşüm sırasında DOMSource'a dönüşmeden önce belgeyi ayrıştırabilirsiniz, ancak her iki şekilde de DTD istisnası oluşmaz.Yani bu "çözüm" hiçbir şeyi çözmez ve sadece yanlış yönlendirir. – mvmn

3

Dene:

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

Şu anda belge işlevi çağrılırken (2) dış XHTML sayfaları analiz etmek XSLT'de içinde aynı sorunla karşılaşıyorum. Eğer

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 

Eğer AŞAĞIDAKİ koduyla dtd doğrulama devre dışı deneyebilirsiniz kullanırsanız

0

:

dbf.setValidating(false); 
+0

Chris'in cevabını görün, tam olarak aynı. – theomega

2

önceki cevaplar çözüm götürdü ama bu yüzden benim için belli değildi İşte tam bir tane:

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