Является ли 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 и отказываться от сетевого трафика.

В любом случае, так я его исправляю. Я всегда забываю. Я всегда получаю ошибку. Я всегда получаю этот распознаватель. Затем я снова занялся бизнесом.