هل Scala / Java لا يحترم W3 "الزائد حركة المرور DTD" المواصفات؟

StackOverflow https://stackoverflow.com/questions/1096285

  •  11-09-2019
  •  | 
  •  

سؤال

أنا جديد في scala، لذلك قد أكون خارج القاعدة في هذا، أريد أن أعرف ما إذا كانت المشكلة هي رمزي. بالنظر إلى HttpPly ملف Scala، المبسطة إلى:

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...

لقد رأيت كومة تجاوز الموضوع في هذا فيما يتعلق جافا، وكذلك دخول فريق نظام W3C بلوق حول عدم محاولة الوصول إلى DTD هذا عبر الويب. لقد عزلت أيضا الخطأ في طريقة XML.Load ()، وهي طريقة مكتبة SCALA بقدر ما أستطيع أن أقول.

سؤالي: كيف يمكنني إصلاح هذا؟ هل هذا شيء هو منتج حسب المنتج (Cribbed من وظيفة رافائيل فيريرا)، وهو منتج لشيء من جافا محددة أحتاج لمعالجة كما هو الموضوع السابق, ، أو شيء ما هو scala محددة؟ أين تحدث هذه المكالمة، وهل هو خطأ أو ميزة؟ في"هل أنا؟ إنها هي، أليس كذلك؟")

هل كانت مفيدة؟

المحلول 5

إنها تعمل. بعد بعض أعمال المباحث، التفاصيل الخاصة بأفضل ما أستطيع معرفةها:

في محاولة لتحليل واجهة مريحة في التنموية، أقوم ببناء المحلل المحلل والحصول على خطأ أعلاه (بدلا من ذلك، متشابه). أحاول معلمات مختلفة لتغيير إخراج XML، ولكن احصل على نفس الخطأ. أحاول الاتصال بمستند XML الذي سوط بسرعة (CRIBBED بغباء من الواجهة نفسها) والحصول على نفس الخطأ. ثم أحاول الاتصال بأي شيء، فقط للركلات، والحصول على نفس الخطأ (مرة أخرى، فقط مماثلة) خطأ.

بدأت استجواب ما إذا كان خطأ في المصادر أو البرنامج، لذلك بدأت البحث عنها، ويبدو وكأنه مشكلة مستمرة - مع العديد من Google وهكذا يضرب نفس الموضوع. هذا، لسوء الحظ، جعلني أركز على جوانب المنبع (اللغة) من الخطأ، بدلا من استكشاف الأخطاء وإصلاحها المزيد من المصب في المصادر أنفسهم.

سريع إلى الأمام والمحلل يعمل فجأة على أصلي إخراج XML. أكدت أنه كان هناك بعض الأعمال الإضافية قد قام بجانب الخادم (مجرد صدفة مجنونة؟). ليس لدي إما XML سابقا ولكنه يشك في أنه يرتبط مع تغيير معرفات المستندات التي يتم تغييرها.

الآن، يعمل المحلل المحلل بشكل جيد على الواجهة المريحة، وكذلك أي XML منسق بشكل جيد أستطيع أن رمي عليه. كما فشل في جميع XHTML DTD الذي جربته (مثل www.w3.org). هذا مخالف لما تتوقعهseReilly، ولكن يبدو أنه يغي ما دول W3.

ما زلت جديدا في SCALA، لذلك لا يمكن تحديد ما إذا كان لدي حالة خاصة أو نموذجية. ولا يمكنني التأكد من أن هذه المشكلة لن تعاد حدوثها لي في شكل آخر أسفل الخط. يبدو أن سحب XHTML سيستمر في التسبب في هذا الخطأ ما لم يستخدم المرء حلا مشابها لتلك التي اقترحتها gclaraMunt $ @ J-16 SDIZ. أنا لست مؤهلا حقا لمعرفة ما إذا كانت هذه مشكلة في اللغة، أو تنفيذ الحل (المحتمل لاحقا)

بالنسبة للإطار الزمني الفوري، أظن أن أفضل حل سيكون بالنسبة لي لضمان ذلك المستطاع لتحليل هذا مصدر XML - بدلا من معرفة أن الآخر كان لديه نفس الخطأ ويفترض أن هناك مشكلة وظيفية مع اللغة.

آمل أن يساعد هذا الآخرين.

نصائح أخرى

لقد صدمت في نفس المشكلة، وأنا لم أجد حلا أنيقا (أفكر في نشر السؤال إلى القائمة البريدية SCALA) في الوقت نفسه، وجدت الحل البديل: قم بتنفيذ SaxParSerFactorMLLIMPL الخاص بك حتى تتمكن من ضبط F .setfeature ("http://apache.org/xml/features/disallow-doctype-decl."، صحيح)؛ الممتلكات. الشيء الجيد هو أنه لا يتطلب أي تغيير رمز إلى قاعدة كود 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 أيضا)

وفي كود 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"
}

الآن، وضعت أن الاشياء MyXML داخل fchandparseurl فقط للحفاظ على هيكل المثال على أنها لم تتغير قدر الإمكان. للاستخدام الفعلي، سأفصل فيه في كائن أعلى مستوى، وجعل "المحلل المحلل" في DAF بدلا من 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()
  }
}

استيراد الحزمة التي يتم تعريفها، وأنت جيد للذهاب.

عمل حل 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")

هذه مشكلة 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     }

هناك مشكلتان مع ما تحاول القيام به:

  • يحاول محلل XML في Scala استرجاع DTD فعليا عندما لا ينبغي ذلك. يبدو أن J-16 SDIZ لديها بعض النصائح لهذه المشكلة.
  • صفحة overflow المكدس التي تحاول تحليلها ليست XML. انها html4 صارمة.

المشكلة الثانية غير ممكنة حقا لإصلاحها في رمز SCALA الخاص بك. حتى بمجرد أن تحصل حول مشكلة DTD، ستجد أن المصدر غير صحيح فقط XML (لا يتم إغلاق العلامات الفارغة بشكل صحيح، على سبيل المثال).

يجب عليك إما تحليل الصفحة مع شيء إلى جانب محلل XML، أو التحقيق في استخدام أداة مساعدة مثل Tidy لتحويل HTML إلى XML.

معرفتي من Scala سيئة للغاية، لكنها لا تستطيع استخدامها بناء البحارة في حين أن؟

  val xml = new java.io.File("xmlWithDtd.xml")
  val parser = scala.xml.parsing.ConstructingParser.fromFile(xml, true)
  val doc = parser.document()
  println(doc.docElem)

ل Scala 2.7.7 تمكنت من القيام بذلك مع scala.xml.parsing.xhtmlparser

إعداد Xerces Switches يعمل فقط إذا كنت تستخدم Xerces. يعمل محلل الكيان لأي محلل JAXP.

هناك المزيد من القراءات المعممة هناك، ولكن هذا التنفيذ يقوم بالحيلة عندما يكون كل ما أحاول القيام به هو تحليل XHTML صحيح.

http://code.google.com/p/java-xhtml-cache-ddds-entityresolver/

يوضح كيف هو تخزين DTDS وتخخير حركة مرور الشبكة.

في أي حال، هذا هو كيف يمكنني إصلاحه. وبعد أنا دائما أنسى. أنا دائما الحصول على الخطأ. أنا دائما أذهب جلب هذا محلي الكيان. ثم عدت في العمل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top