我正在将代码从应用程序的一部分(applet)复制到应用程序内部。我正在将XML解析为String。自从我解析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文件放在类路径上。
答案 0 :(得分:4)
我认为你在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上设置Schema。
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 :(得分:4)
问题在于:
<a href="http://www.mycomp.com/MyComp.dtd">http://www.mycomp.com/MyComp.dtd</a>
是HTML超链接,而不是URL。替换为:
http://www.mycomp.com/MyComp.dtd
答案 2 :(得分:1)
由于此XML来自外部源,因此首先要向他们抱怨他们发送的XML无效。
作为一种变通方法,您可以在解析器上设置EntityResolver,将SystemId与此无效网址进行比较,并返回正确的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;
}
}
}
);