2010-09-09 32 views
6

Tôi đang sao chép mã từ một phần của ứng dụng (applet) vào bên trong ứng dụng. Tôi đang phân tích cú pháp XML dưới dạng Chuỗi. Đã một thời gian kể từ khi tôi phân tích cú pháp XML, nhưng từ lỗi được ném, có vẻ như nó có thể liên quan đến việc không tìm thấy .dtd. Stack trace làm cho nó khó khăn để tìm ra nguyên nhân chính xác của lỗi này, nhưng đây là thông điệp:Tại sao tôi nhận được "MalformedURLException: không có giao thức" khi sử dụng SAXParser?

java.net.MalformedURLException: no protocol: <a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a> 

và XML có này là vài dòng đầu tiên:

<?xml version='1.0'?> 
<!DOCTYPE MYTHING SYSTEM '<a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a>'> 

và đây là mã có liên quan snippets

class XMLImportParser extends DefaultHandler { 

    private SAXParser m_SaxParser = null; 
    private String is_InputString = ""; 

    XMLImportParser(String xmlStr) throws SAXException, IOException { 
    super(); 
    is_InputString = xmlStr; 
    createParser(); 
    try { 
     preparseString(); 
     parseString(is_InputString); 
    } catch (Exception e) { 
     throw new SAXException(e); //"Import Error : "+e.getMessage()); 
    } 
    } 

    void createParser() throws SAXException { 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    factory.setValidating(true); 
    try { 
     factory.setFeature("http://xml.org/sax/features/namespaces", true); 
     factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); 
     m_SaxParser = factory.newSAXParser(); 
     m_SaxParser.getXMLReader().setFeature("http://xml.org/sax/features/namespaces", true); 
     m_SaxParser.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes", true); 
    } catch (SAXNotRecognizedException snre){ 
     throw new SAXException("Failed to create XML parser"); 
    } catch (SAXNotSupportedException snse) { 
     throw new SAXException("Failed to create XML parser"); 
    } catch (Exception ex) { 
     throw new SAXException(ex); 
    } 
    } 

    void preparseString() throws SAXException { 
    try { 
     InputSource lSource = new InputSource(new StringReader(is_InputString)); 
     lSource.setEncoding("UTF-8"); 
     m_SaxParser.parse(lSource, this); 
    } catch (Exception ex) { 
     throw new SAXException(ex); 
    } 
    } 

} 

Dường như các lỗi đang xảy ra trong phương pháp preparseString(), trên dòng thực hiện các phân tích, dòng m_SaxParser.parse(lSource, this);.

FYI, tệp 'MyComp.dtd' không tồn tại ở vị trí đó và có thể truy cập qua http. Tệp XML xuất phát từ một dịch vụ khác trên máy chủ, vì vậy tôi không thể thay đổi nó thành định dạng tệp: // và đặt tệp .dtd trên đường dẫn lớp.

Trả lời

4

Tôi nghĩ rằng bạn có thêm một số mã trong khai báo XML. Hãy thử điều này:

<?xml version='1.0'?> 
<!DOCTYPE MYTHING SYSTEM "http://www.mycomp.com/MyComp.dtd"> 

Trên đây bị bắt từ các khuyến nghị của W3C: http://www.w3.org/QA/2002/04/valid-dtd-list.html

Bạn có thể sử dụng liên kết http để thiết lập các Schema trên SAXParserFactory trước khi tạo phân tích cú pháp của bạn.

void createParser() throws SAXException { 
    Schema schema = SchemaFactory.newSchema(new URL("http://www.mycomp.com/MyComp.dtd")); 
    SAXParserFactory factory = SAXParserFactory.newInstance(); 
    factory.setValidating(true); 
    factory.setSchema(schema); 
+0

Cảm ơn đã phản ứng nhanh chóng. Tôi nghĩ đây là câu trả lời hoàn chỉnh hơn với thẻ DOCTYPE đã được sửa hoàn chỉnh. Vui lòng xem câu hỏi của tôi ở trên về khả năng bỏ qua thẻ DOCTYPE này vì tôi nhận được từ một nguồn bên ngoài. – user26270

+0

cảm ơn câu trả lời nhanh chóng – user26270

+0

Bạn có thể đặt Giản đồ trên SAXParserFactory thành một lược đồ được tạo từ liên kết http. Tôi sẽ đăng chỉnh sửa lên câu trả lời ở trên. –

4

Vấn đề là điều này:

<a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a> 

là một siêu liên kết HTML, không phải là một URL. Thay thế nó bằng cách này:

http://www.mycomp.com/MyComp.dtd 
+0

Cảm ơn, điều đó đã xảy ra. Tôi đã có một bản sao cục bộ của Xml và thay đổi nó. Tuy nhiên, khi chạy trực tiếp, tôi không thể sửa đổi dòng DOCTYPE này vì tôi nhận được nó từ một dịch vụ bên ngoài. Vậy có cách nào để nói cho trình phân tích cú pháp bỏ qua nó không? Tôi thấy tài liệu tham khảo để xác nhận/không xác nhận trong các phần khác của mã khiến tôi tự hỏi nếu không xác thực sẽ làm cho nó bỏ qua tham chiếu dtd xấu. – user26270

+0

Đặt trình phân tích cú pháp của bạn thành không xác thực sẽ khiến toàn bộ DTD bị bỏ qua. Lý do để có DTD là để trình phân tích cú pháp có thể xác nhận hợp lệ XML đầu vào dựa vào nó. –

+0

@ codeman73 - bạn nên cố gắng lấy bất cứ thứ gì cho bạn biết DOCTYPE đã được sửa. Rõ ràng là không có thật. –

1

Vì XML này đến từ nguồn bên ngoài, điều đầu tiên cần làm là phàn nàn với họ rằng họ đang gửi XML không hợp lệ.

Là một khắc phục, bạn có thể thiết lập một EntityResolver trên phân tích cú pháp của bạn mà so sánh SystemId để url không hợp lệ này và trả về một url http đúng:

m_SaxParser.getXMLReader().setEntityResolver(
    new EntityResolver() { 
     public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException { 
      if ("<a href=\"http://www.mycomp.com/MyComp.dtd\">http://www.mycomp.com/MyComp.dtd</a>".equals(systemId)) { 
       return new InputSource("http://www.mycomp.com/MyComp.dtd"); 
      } else { 
       return null; 
      } 
     } 
    } 
); 
Các vấn đề liên quan