لماذا أحصل على "مشوهات الإطار: لا يوجد بروتوكول" عند استخدام Saxparser؟

StackOverflow https://stackoverflow.com/questions/3677517

  •  01-10-2019
  •  | 
  •  

سؤال

أقوم بنسخ التعليمات البرمجية من جزء واحد من تطبيقنا (التطبيق) إلى داخل التطبيق. أنا تحليل XML كسلسلة. لقد كان الوقت لحظة منذ تحليل XML ، ولكن من الخطأ الذي تم إلقاؤه يبدو أنه قد يكون له علاقة بعدم العثور على .DTD. تتبع المكدس يجعل من الصعب العثور على السبب الدقيق للخطأ ، ولكن إليك الرسالة:

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

و XML لديه هذا كأول خطين:

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

وإليك قصاصات الكود ذات الصلة

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

}

يبدو أن الخطأ يحدث في طريقة preparsestring () ، على السطر الذي يقوم بالفعل بالتحليل ، m_SaxParser.parse(lSource, this); خط.

FYI ، يوجد ملف "MyComp.dtd" في هذا الموقع ويمكن الوصول إليه عبر HTTP. يأتي ملف XML من خدمة مختلفة على الخادم ، لذلك لا يمكنني تغييره إلى ملف: // format ووضع ملف .dtd على classpath.

هل كانت مفيدة؟

المحلول

أعتقد أن لديك بعض التعليمات البرمجية الإضافية في إعلان XML. جرب هذا:

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

تم القبض على ما سبق من توصيات W3C: http://www.w3.org/qa/2002/04/valid-dtd-list.html

يمكنك استخدام رابط HTTP لتعيين المخطط على saxparserfactory قبل إنشاء المحلل.

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

نصائح أخرى

المشكلة هي أن هذا:

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

هو ارتباط تشعبي HTML ، وليس عنوان URL. استبدله بهذا:

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

نظرًا لأن XML يأتي من مصدر خارجي ، فإن أول ما يجب فعله هو تقديم شكوى لهم أنهم يرسلون XML غير صالح.

كحل بديل ، يمكنك ضبط entityResolver على جهاز المحلل الخاص بك والذي يقارن SystemId بعنوان URL غير صالح ويعيد عنوان URL الصحيح HTTP:

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;
            }
        }
    }
);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top