Почему я получаю "MalformedURLException: нет протокола" при использовании SAXParser? - PullRequest
6 голосов
/ 09 сентября 2010

Я копирую код из одной части нашего приложения (апплета) внутрь приложения. Я анализирую 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);.

К вашему сведению, файл 'MyComp.dtd' существует в этом месте и доступен через http. Файл XML поступает из другой службы на сервере, поэтому я не могу изменить его на формат file: // и поместить файл .dtd в путь к классам.

Ответы [ 3 ]

4 голосов
/ 09 сентября 2010

Проблема в том, что это:

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

- гиперссылка HTML, а не URL.Замените его следующим:

http://www.mycomp.com/MyComp.dtd
4 голосов
/ 09 сентября 2010

Я думаю, у вас есть дополнительный код в декларации 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);
1 голос
/ 09 сентября 2010

Поскольку этот XML поступает из внешнего источника, первое, что нужно сделать, - это пожаловаться им на то, что они отправляют недопустимый XML.

В качестве обходного пути вы можете установить EntityResolver в своем синтаксическом анализаторе, который сравнивает SystemId с этим недействительным URL-адресом и возвращает правильный http-URL:

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