是的斯卡拉/Java不尊重w3"过剩dtd业务"规格?
题
我是新来的卡拉,因此我可能是基地在此,我想知道如果问题是我的代码。鉴于卡拉的文件httpparse,简化:
object Http {
import java.io.InputStream;
import java.net.URL;
def request(urlString:String): (Boolean, InputStream) =
try {
val url = new URL(urlString)
val body = url.openStream
(true, body)
}
catch {
case ex:Exception => (false, null)
}
}
object HTTPParse extends Application {
import scala.xml._;
import java.net._;
def fetchAndParseURL(URL:String) = {
val (true, body) = Http request(URL)
val xml = XML.load(body) // <-- Error happens here in .load() method
"True"
}
}
这是与(URL并不重要,这是一个玩笑例):
scala> HTTPParse.fetchAndParseURL("http://stackoverflow.com")
结果总是:
java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/html4/strict.dtd
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1187)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:973)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEnti...
我已经看到的 堆溢出线 在这相对于Java,以及 W3C的系统团队的博客入口 关于不试图访问这DTD通过网。我还孤立的错误的XML。load()方法,这是一个卡拉库方法尽我所能告诉。
我的问题:我如何能解决这个问题? 是这个东西是一个由的产物,我的代码(从三份文件的内容 拉斐尔*费雷拉的后),一个产品的东西Java具体的,我需要地址在 前线, 或者东西这是卡拉特?这是哪里的话发生的事情,它是一个错误或功能?("这是我的吗?这是她的,对不对?")
解决方案 5
它的工作原理。经过一番侦查工作,细节,尽我所能领会它们:
试图解析发育RESTful接口,我建立解析器并获得上述(相反,一个类似的)错误。我尝试各种参数来改变XML输出,但得到了同样的错误。我尝试连接到一个XML文档,我很快就掀起(从界面本身愚蠢那儿剽窃),并得到同样的错误。然后,我尝试连接到任何东西,只是踢,并获得相同的(同样,只可能相似)的错误。
我开始质疑它是否是与源或程序中的错误,所以我就开始四处寻找,它看起来像有许多谷歌的持续发出─和SO击中同一主题。此,不幸的是,让我集中在错误的上游(语言)方面,而不是排除在源本身更下游。
快进和快解析器突然工程对的原始的XML输出。我证实,有一些额外的工作已经完成,服务器端(只是一个疯狂的巧合吗?)。我没有任何早期的XML,但怀疑它正在改变相关的文件标识符。
现在,解析器工作正常的RESTful接口上,以及任何格式良好的XML我可以扔了。它也没有在所有的XHTML DTD的我已经试过(例如www.w3.org)。这是相反的是@SeanReilly预期,但似乎与到JIVE什么W3状态的。
我还是新来的Scala,所以不能确定如果我有一个特殊的或典型案例。我也不能放心,这个问题不会对我的另一种形式的路线再次出现。它似乎是拉动XHTML将继续导致此错误除非使用类似于由@GClaramunt $ @ J-16 SDiZ建议已经使用了一个解决方案。我不是真的有资格知道这是与语言有问题,还是我执行的解决方案(可能是更高版本)
的在不久的时间内,我怀疑是最好的解决办法一直对我保证,这是的可能的解析该XML source--,而不是看到其他的也有同样的错误并假定有一个与语言的功能的问题。
希望这有助于他人。
其他提示
我碰到了同样的问题,我还没有找到一个很好的解决方案(我想进入张贴问题Scala的邮件列表)。同时,我发现了一个解决办法:实现自己的SAXParserFactoryImpl这样你就可以设置f.setFeature(“ http://apache.org/xml/features/disallow -doctype-DECL ”,TRUE);属性。好事是它不需要更改任何代码到Scala代码库(我同意,这应该是固定的,虽然)。 首先,我延伸的默认解析器工厂:
package mypackage;
public class MyXMLParserFactory extends SAXParserFactoryImpl {
public MyXMLParserFactory() throws SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException {
super();
super.setFeature("http://xml.org/sax/features/validation", false);
super.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
super.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
super.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
}
}
没什么特别的,我只是想设置属性的机会。
(注意:这是普通的Java代码,很可能是你可以写在斯卡拉同太)
而在你的Scala代码,你需要配置JVM使用新的工厂:
System.setProperty("javax.xml.parsers.SAXParserFactory", "mypackage.MyXMLParserFactory");
然后,可以调用XML.load未经验证
如果不解决,现在,你能指望什么问题,到如果函数返回的请求之下虚假怎样?
def fetchAndParseURL(URL:String) = {
val (true, body) = Http request(URL)
什么的将会的发生是一个异常将被抛出。你可以这样改写它,虽然:
def fetchAndParseURL(URL:String) = (Http request(URL)) match {
case (true, body) =>
val xml = XML.load(body)
"True"
case _ => "False"
}
现在,来解决XML解析的问题,我们将在解析器禁用DTD装载,别人的建议:
def fetchAndParseURL(URL:String) = (Http request(URL)) match {
case (true, body) =>
val f = javax.xml.parsers.SAXParserFactory.newInstance()
f.setNamespaceAware(false)
f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
val MyXML = XML.withSAXParser(f.newSAXParser())
val xml = MyXML.load(body)
"True"
case _ => "False"
}
现在,我把里面fetchAndParseURL MyXML东西只是为了保持例子的结构不变越好。对于实际使用,我在顶层对象将其分离,以及使“解析器”变成DEF代替缬氨酸,以避免与可变解析器问题:
import scala.xml.Elem
import scala.xml.factory.XMLLoader
import javax.xml.parsers.SAXParser
object MyXML extends XMLLoader[Elem] {
override def parser: SAXParser = {
val f = javax.xml.parsers.SAXParserFactory.newInstance()
f.setNamespaceAware(false)
f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
f.newSAXParser()
}
}
导入它在定义的包,你是好去。
GClaramunt的解决方案能给我带来惊奇。我的Scala转换如下:
package mypackage
import org.xml.sax.{SAXNotRecognizedException, SAXNotSupportedException}
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
import javax.xml.parsers.ParserConfigurationException
@throws(classOf[SAXNotRecognizedException])
@throws(classOf[SAXNotSupportedException])
@throws(classOf[ParserConfigurationException])
class MyXMLParserFactory extends SAXParserFactoryImpl() {
super.setFeature("http://xml.org/sax/features/validation", false)
super.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
super.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false)
super.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
}
由于提到了他原来的职位,就必须把下面的行代码中的某个地方:
System.setProperty("javax.xml.parsers.SAXParserFactory", "mypackage.MyXMLParserFactory")
这是一个阶的问题。本地Java有一个选项来禁用加载DTD:
f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
有在阶没有等效。
如果你有点想自己解决这个问题,检查scala/xml/parsing/FactoryAdapter.scala
并把线
278 def loadXML(source: InputSource): Node = {
279 // create parser
280 val parser: SAXParser = try {
281 val f = SAXParserFactory.newInstance()
282 f.setNamespaceAware(false)
< - 在此处插入
283 f.newSAXParser()
284 } catch {
285 case e: Exception =>
286 Console.err.println("error: Unable to instantiate parser")
287 throw e
288 }
有两个问题有什么你想要做的:
- 斯卡拉的xml parser是试图身体检索DTD时,它不应该。J-16SDiZ似乎有一些建议为这一问题。
- 堆溢页你是在试图分析不XML。这是Html4严格。
第二个问题是不是真的能够解决在卡拉代码。即使是一旦你得到周围的dtd问题,你会发现的源只是不是有效的XML(空标签不正确关闭,例如)。
你有两分析页上的东西除了XML parser,或调查使用的实用程序,如整洁的转换html于xml。
我的斯卡拉的知识是非常不好的,但不能使用的 ConstructingParser 代替?
val xml = new java.io.File("xmlWithDtd.xml")
val parser = scala.xml.parsing.ConstructingParser.fromFile(xml, true)
val doc = parser.document()
println(doc.docElem)
有关阶2.7.7我管理符合scala.xml.parsing.XhtmlParser做到这一点
设置的Xerces只有开关,如果你正在使用的Xerces工作。实体解析器适用于任何JAXP解析器。
有更广义的实体解析器在那里,但这个实现的伎俩,当所有我想要做的是分析有效的XHTML。
http://code.google.com/p/ java的XHTML的高速缓存的DTD-的EntityResolver /
表明它是如何琐碎缓存DTD和放弃的网络流量。
在任何情况下,这是如何解决它。我总是忘了。我总是得到错误。我经常去获取这个实体解析器。然后我又回到企业。