我有一个很奇怪的情况:

我尝试使用默认的Java XML解析器解析多个符合XHTML的网站。解析期间(而不是下载期间)测试块。

这可能是错误,还是解析器尝试在解析过程中尝试下载其他参考资源(这将是“不错的”反功能)?

使用简单的数据,它就可以工作。 (TEST1)
对于复杂的数据,它会阻塞。 (TEST2)
(我尝试了en.wikipedia.orgvalidator.w3.org

发生阻塞时,CPU处于空闲状态。

用JDK6和JDK7测试,结果相同。

请查看测试用例,源可以复制+粘贴+运行。

资源

import java.io.*;
import java.net.*;
import java.nio.charset.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.*;

public class _XmlParsingBlocks {

  private static Document parseXml(String data)
      throws Exception {
    Transformer t = TransformerFactory.newInstance().newTransformer();
    DocumentBuilder b = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    DOMResult out = new DOMResult(b.newDocument());
    t.transform(new StreamSource(new StringReader(data)), out);
    return (Document) out.getNode();
  }

  private static byte[] streamToByteArray(InputStream is)
      throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    for (;;) {
      byte[] buffer = new byte[256];
      int count = is.read(buffer);
      if (count == -1) {
        is.close();
        break;
      }
      baos.write(buffer, 0, count);
    }

    return baos.toByteArray();
  }

  private static void test(byte[] data)
      throws Exception {
    String asString = new String(data, Charset.forName("UTF-8"));

    System.out.println("===== PARSING STARTED =====");
    Document doc = parseXml(asString);
    System.out.println("===== PARSING ENDED =====");
  }

  public static void main(String[] args)
      throws Exception {
    {
      System.out.println("********** TEST 1");
      test("<html>test</html>".getBytes("UTF-8"));
    }

    {
      System.out.println("********** TEST 2");
      URL url = new URL("http://validator.w3.org/");
      URLConnection connection = url.openConnection();
      InputStream is = connection.getInputStream();
      byte[] data = streamToByteArray(is);
      System.out.println("===== DOWNLOAD FINISHED =====");

      test(data);
    }
  }

}


输出量

********** TEST 1
===== PARSING STARTED =====
===== PARSING ENDED =====
********** TEST 2
===== DOWNLOAD FINISHED =====
===== PARSING STARTED =====

[here it blocks]

最佳答案

在过去的几个月中,W3C开始阻止对常见DTD(例如XHTML DTD)的请求-它们无法应付所产生的流量。如果您不使用缓存DTD的代理服务器,则需要使用EntityResolver或目录将引用重定向到本地副本。

10-04 10:57
查看更多