XML解析接続タイムアウト


この記事は以下のとおりです.     http://blog.csdn.net/chjttony/article/details/7720873
前を言う
    XMLを読み取るとき、なぜ接続がタイムアウトしたのか、XML解析がどのようにネットワークにアクセスするのか分からない人が多いが、実はXML解析の前に、XMLがDTDファイルを指定すると、JavaはDTDファイルの経路に基づいてローカル検索やリモートダウンロードを行い、ダウンロードすると接続タイムアウトが発生する!だから接続のタイムアウトを避けるために、DTDのダウンロードを避けることができて、以下は2つの方式を通じてDTDのダウンロードを避けることができて、本人は自分で測って、確かに1篇の良い文章で、作者に感謝します!
    
次は本文です.
Javaプログラムはxmlファイルを解析する際、xmlファイルにdtdが指定されている場合、デフォルトでは指定されたurlからdtdファイルがダウンロードされますが、ネットワーク接続ができない場合やファイアウォールの原因でdtdファイルがダウンロードできない場合、プログラムが接続タイムアウト異常を報告し、xmlの解析に失敗することが多いです.このクラスの問題を解決するには、次の2つの方法があります.
1.dtdファイルをローカルから読み込むことを指定
解析するxmlファイルに次のdtd宣言があります.
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "
http://docs.oasisopen.org/dita/v1.2/os/dtd1.2/technicalContent/dtd/concept.dtd
">

publicId:参照される外部エンティティの共通識別子で、指定されていない場合nullです.
                上記dtd宣言でpublicIdは-//OASIS//TD DITA Concept/EN
SystemId:参照される外部エンティティのシステム識別子.
                 上記dtd宣言でsystemIdはhttp://docs.oasis-open.org/dita/v1.2/os/dtd1.2/technicalContent/dtd/concept.dtd
再SAXのEntityResolverクラスのresolveEntity(String) publicId, String systemId) throws SAXException, IOExceptionメソッドは、XML解析器がxmlを解析する前に呼び出され、指定したdtdファイルをロードするためにローカルのdtdファイルを読み込むことを指定します.
/**
 * Implementation of <code>org.xml.sax.EntityResolver</code> that loads
 * entitities (for example dtd files) from the classpath.
 */
public class ClasspathEntityResolver
    implements EntityResolver
{
    public InputSource resolveEntity(String publicId, String systemId)
        throws SAXException, IOException
    {
     
        if (systemId != null)
        {
           
            int index = systemId.lastIndexOf('/');
            if (index != -1)
            {
             systemId = systemId.substring(index + 1);
            }
            systemId = "/" + systemId;
            InputStream istr = Thread.currentThread().getContextClassLoader().getResourceAsStream(systemId);
            if (istr != null)
            {
                return new InputSource(istr);
            }
        }
        return null;
    }
}

SAXでxmlファイルを解析する前に、カスタムClasspathEntityResolverを使用することを指定します.
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser(); 
xmlReader = saxParser.getXMLReader();
xmlReader.setEntityResolver(new ClasspathEntityResolver());
xmlReader.setContentHandler(handler);
try {
 xmlReader.parse(new InputSource(inputFilePath));
 } catch (Exception e) {
  e.printStackTrace();
 }

注意:
  試験により、この方法はSYSTEM(ローカルdtd)にのみ有効であることが分かった.
<!DOCTYPE concept PUBLIC "-//OASIS//DTD DITA Concept//EN" "
http://docs.oasisopen.org/dita/v1.2/os/dtd1.2/technicalContent/dtd/concept.dtd
">

  PUBLIC方式のdtdは依然として外部からdtdをダウンロードしており、第2の方式でdtdチェックを無視するしかない.
2.xmlファイルを解析するときにdtdを完全に無視する:
SAX解析器は指定できますhttp://apache.org/xml/features/nonvalidating/load-external-dtdプロパティを使用してdtdを無視するかどうかを決定します.例は次のとおりです.
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
    
xmlReader = saxParser.getXMLReader();
xmlReader.setFeature("
http://apache.org/xml/features/nonvalidating/load-external-dtd
", false);
xmlReader.setContentHandler(handler);
try {
xmlReader.parse(new InputSource(inputFilePath));
} catch (Exception e) {
e.printStackTrace();
}