Является ли Scala/Java несоблюдением спецификаций w3 "превышение dtd трафика"?
Я новичок в Scala, поэтому я могу отказаться от этого, я хочу знать, является ли проблема моим кодом. С учетом Scala файла 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 System Team о том, что вы не пытаетесь получить доступ к этому DTD через Интернет. Насколько я могу сказать, я также выделил ошибку для метода XML.load(), который является библиотечным методом Scala.
Мой вопрос: как я могу это исправить? Является ли это чем-то, что является продуктом моего кода (cribbed from Raphael Ferreira), по продукту какого-то Java-специфического, который мне нужно адресовать, как в предыдущем потоке, или что-то, что является Scala конкретным? Где этот вызов происходит, и это ошибка или функция? ( "Это я? Это она, верно?" )
Ответы
Ответ 1
Это работает. После какой-то детективной работы детали, как я могу их понять:
Попытка разобрать интерфейс RESTful для разработки, я создаю синтаксический анализатор и получаю вышеуказанную (скорее, аналогичную) ошибку. Я пытаюсь использовать различные параметры для изменения вывода XML, но получаю ту же ошибку. Я пытаюсь подключиться к XML-документу, который я быстро взламываю (глупо сбитый с самого интерфейса) и получаю ту же ошибку. Затем я пытаюсь подключиться ко всему, только для ударов, и получить ту же (опять же, скорее всего, только аналогичную) ошибку.
Я начал расспрашивать, была ли ошибка с источниками или программой, поэтому я начал искать, и это похоже на текущую проблему - со многими хитами Google и SO по той же теме. Это, к сожалению, заставило меня сосредоточиться на аспектах ошибки выше по течению (на языке), а не на устранении неполадок более нисходящего потока в самих источниках.
Быстрая перемотка вперед, и синтаксический анализатор внезапно работает на исходном выходе XML. Я подтвердил, что была сделана некоторая дополнительная работа на стороне сервера (просто сумасшедшее совпадение?). У меня нет ни одного ранее XML, но я подозреваю, что он связан с изменяемыми идентификаторами документа.
Теперь синтаксический анализатор отлично работает на интерфейсе RESTful, а также любой хорошо отформатированный XML, который я могу на него набросить. Он также терпит неудачу во всех XHTML DTD, которые я пробовал (например, www.w3.org). Это противоречит тому, что ожидает @SeanReilly, но, похоже, с помощью состояния W3.
Я все еще новичок в Scala, поэтому не могу определить, есть ли у меня специальный или типичный случай. Я также не могу быть уверен, что эта проблема не будет повторяться для меня в другой форме по линии. Похоже, что вытягивание XHTML будет продолжать вызывать эту ошибку, если вы не используете решение, подобное тем, которые были предложены с помощью @GClaramunt [email protected] SDiZ. Я не знаю, действительно ли это проблема с языком или моя реализация решения (вероятно, позже)
В ближайшее время я подозреваю, что лучшее решение для меня было бы гарантировать, что можно было бы проанализировать этот источник XML - вместо того, чтобы видеть, что другие имели ту же ошибку и предполагали, что существует функциональная проблема с языком.
Надеюсь, что это поможет другим.
Ответ 2
Я столкнулся с проблемой SAME, и я не нашел изящного решения (я собираюсь разместить вопрос в списке рассылки Scala). Тем временем я нашел обходное решение: реализовать собственный SAXParserFactoryImpl так вы можете установить f.setFeature( " http://apache.org/xml/features/disallow-doctype-decl", true); имущество. Хорошо, что это не требует какого-либо изменения кода в базе кода Scala (я согласен, что он должен быть исправлен, хотя).
Сначала я расширяю парсер по умолчанию factory:
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)
И в вашем коде Scala вам нужно настроить JVM для использования вашего нового factory:
System.setProperty("javax.xml.parsers.SAXParserFactory", "mypackage.MyXMLParserFactory");
Затем вы можете вызвать XML.load без проверки
Ответ 3
Без адресации, на данный момент проблема, что вы ожидаете, если запрос функции возвращает false ниже?
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"
}
Теперь я помещаю этот материал MyXML внутри fetchAndParseURL только для того, чтобы сохранить структуру примера как можно более неизменной. Для фактического использования я бы разделил его на объект верхнего уровня и сделал "парсер" в def вместо val, чтобы избежать проблем с изменяемыми анализаторами:
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()
}
}
Импортируйте пакет, в который он определен, и вы хорошо пойдете.
Ответ 4
Решение 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")
Ответ 5
Это проблема scala. У родной Java есть возможность отключить загрузку DTD:
f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
В scala нет эквивалента.
Если вы немного хотите исправить это, проверьте 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 }
Ответ 6
Есть две проблемы с тем, что вы пытаетесь сделать:
- Scala XML-парсер пытается физически извлечь DTD, если это не так. J-16 SDiZ, похоже, имеет некоторые рекомендации по этой проблеме.
- Страница, которую вы пытаетесь разобрать, - это не XML. Это Html4 строгое.
Вторая проблема не может быть исправлена в коде scala. Даже когда вы столкнетесь с проблемой dtd, вы обнаружите, что источник просто недействителен XML (например, пустые теги не закрыты должным образом).
Вам нужно либо проанализировать страницу с чем-то, кроме анализатора XML, либо исследовать с помощью утилиты, например, чтобы преобразовать html в xml.
Ответ 7
Мои знания о Scala довольно бедны, но не могли ли вы использовать 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)
Ответ 8
Для scala 2.7.7 Мне удалось сделать это с помощью scala.xml.parsing.XhtmlParser
Ответ 9
Настройка переключателей Xerces работает только в том случае, если вы используете Xerces. Репрезентатор объекта работает для любого анализатора JAXP.
Есть более обобщенные сущностные решения там, но эта реализация делает трюк, когда все, что я пытаюсь сделать, это проанализировать действительный XHTML.
http://code.google.com/p/java-xhtml-cache-dtds-entityresolver/
Показывает, насколько тривиально кэшировать DTD и отказываться от сетевого трафика.
В любом случае, так я его исправляю. Я всегда забываю. Я всегда получаю ошибку. Я всегда получаю этот распознаватель. Затем я снова занялся бизнесом.