7

我正在将代码从我们的应用程序(一个小程序)的一部分复制到应用程序内部。我将 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 文件放在类路径中。

4

3 回答 3

6

我认为您在 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);
于 2010-09-09T14:30:57.403 回答
4

问题在于:

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

是 HTML 超链接,而不是 URL。用这个替换它:

http://www.mycomp.com/MyComp.dtd
于 2010-09-09T14:34:31.320 回答
1

由于此 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;
            }
        }
    }
);
于 2010-09-09T16:00:42.800 回答