سؤال

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

هل هناك طريقة لجعل SAXReader يتوقف عن قراءة الدفق بمجرد العثور على نهاية عنصر المستند؟هل هنالك طريقة افضل لانجاز هذا؟

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

المحلول

لقد تمكنت من جعل هذا يعمل مع بعض الجمباز باستخدام بعض فئات JAXP الداخلية:

  • قم بإنشاء ماسح ضوئي مخصص، وهو فئة فرعية من XMLNSDocumentScannerImpl
    • قم بإنشاء برنامج تشغيل مخصص، وهو تطبيق XMLNSDocumentScannerImpl.Driver، داخل الماسح الضوئي المخصص الذي يقوم بإرجاع END_DOCUMENT عندما يرى إعلانًا أو عنصرًا.احصل على ScannedEntity من fElementScanner.getCurrentEntity().إذا كان الكيان يحتوي على PushbackReader، فادفع الأحرف غير المقروءة المتبقية في المخزن المؤقت للكيان إلى القارئ.
    • في المُنشئ، يتم استبدال fTrailingMiscDriver بمثيل لبرنامج التشغيل المخصص هذا.
  • قم بإنشاء فئة تكوين مخصصة، وهي فئة فرعية من XIncludeAwareParserConfiguration، التي تحل محل DOCUMENT_SCANNER الخاص بالمخزون بمثيل لهذا الماسح الضوئي المخصص في مُنشئه.
  • قم بتثبيت مثيل لفئة التكوين المخصصة هذه كخاصية "com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration" بحيث يتم إنشاء مثيل لها عندما تحاول فئة SAXReader الخاصة بـ dom4j إنشاء JAXP XMLReader.
  • عند تمرير قارئ إلى أسلوب SAXReader.read() الخاص بـ dom4j، قم بتزويد PushbackReader بحجم مخزن مؤقت أكبر بكثير من الحجم الافتراضي المكون من حرف واحد.يجب أن يكون 8192 على الأقل كافيًا لدعم حجم المخزن المؤقت الافتراضي لـ XMLEntityManager داخل نسخة JAXP من Apache2.

هذا ليس الحل الأنظف، لأنه يتضمن فئات فرعية لفئات JAXP الداخلية، ولكنه يعمل.

نصائح أخرى

وعلى الأرجح، وكنت لا تريد أن يكون لها أكثر من مستند واحد في نفس تيار في نفس الوقت. لا أعتقد أن SAXReader ذكي بما فيه الكفاية لوقف عندما يحصل على نهاية الوثيقة الأولى. لماذا هل من الضروري أن يكون وثائق متعددة في نفس تيار مثل هذا؟

وكنت أعتقد أن لديك لإضافة محول، شيء إلى التفاف تيار ويكون هذا نهاية الأمر عودة ملف عندما يرى بداية المستند المقبلة. وبقدر ما أعرف، موزعي كما هو مكتوب، وسوف تذهب حتى نهاية الملف أو خطأ ... وسوف نرى <?xml version="1.0"?> آخر يكون بالتأكيد خطأ.

وإذا افترضنا أنك مسؤول عن وضع الوثائق في مجرى في المقام الأول يجب أن تكون سهلة لتحديد وثائق في بعض الأزياء. على سبيل المثال:

// Any value that is invalid for an XML character will do.
static final char DOC_TERMINATOR=4;

BOOL addDocumentToStream(BufferedWriter streamOut, char xmlData[])
{
  streamOut.write(xmlData);
  streamOut.write(DOC_TERMINATOR);
}

وبعد ذلك عند قراءة من تيار قراءة في مجموعة حتى مصادفة DOC_TERMINATOR.

char *getNextDocuument(BufferedReader streamIn)
{
  StringBuffer buffer = new StringBuffer();
  int character;

  while (true)
  {
    character = streamIn.read();
    if (character == DOC_TERMINATOR)
      break;

    buffer.append(character);
  }
  return buffer.toString().toCharArray();
}

ومنذ 4 هو قيمة حرف غير صالح سوف لا تواجه إلا إذا قمت بإضافة بشكل صريح. مما يسمح لك لتقسيم الوثائق. الآن مجرد التفاف مجموعة شار resuling للمساهمة في SAX وجيدة ليذهب.

...
  XMLReader xmlReader = XMLReaderFactory.createXMLReader();
...
  while (true)
  {
    char xmlDoc = getNextDocument(streamIn);

    if (xmlDoc.length == 0)
      break;

    InputSource saxInputSource = new InputSource(new CharArrayReader(xmlDoc));
    xmlReader.parse(saxInputSource);
  }
...

لاحظ أن حلقة تنتهي عندما يحصل على وثيقة من طول 0. وهذا يعني أنه يجب عليك إما إضافة DOC_TERMINATOR الثانية بعد الوثيقة الأخيرة من تحتاج إلى إضافة شيء للكشف عن نهاية للتيار في getNextDocument ().

ولقد فعلت هذا من قبل عن طريق wrappering القارئ قاعدة مع قارئ آخر من خلق بلدي التي كانت القدرة على تحليل بسيط للغاية. على افتراض انك تعرف علامة إغلاق للمستند، المجمع بتوزيع لمجرد مباراة، على سبيل المثال ل "". عندما يكشف أن تقوم بإرجاع EOF. المجمع يمكن إجراء التكيف عن طريق تحليل من أول علامة فتح وإعادة EOF على علامة إغلاق مطابقة. لقد وجدت أنه ليس من الضروري للكشف عن الواقع مستوى للعلامة إغلاق منذ أي وثيقة كنت قد استخدمت العلامة ثيقة في حد ذاته، لذلك كان يضمن أن التواجد الأول للعلامة إغلاق المنتهية في الوثيقة.

وعلى ما أذكر، كانت واحدة من الحيل لديك كتلة المجمع قريب ()، لأن القارئ DOM يغلق مصدر الدخل.

وهكذا، نظرا إدخال القارئ، التعليمات البرمجية <م> قد تبدو مثل:

SubdocReader sdr=new SubdocReader(input);
while(!sdr.eof()) {
    sdr.next();
    // read doc here using DOM
    // then process document
    }
input.close();

وطريقة الفولكلوري () يعود صحيحا إذا واجه EOF. طريقة الأعلام التالية () القارئ لوقف عودة -1 للقراءة ().

ونأمل أن هذه النقاط التي في اتجاه مفيد.

و- الكيوي.

وأود أن قراءة دفق الإدخال في مخزن مؤقت داخلي. اعتمادا على الحجم الإجمالي للتيار أتوقع إما قراءة تيار بأكمله ثم تحليل ذلك أو اكتشاف الحدود بين أكس وأخرى (ابحث عن

والفرق الوحيد الحقيقي ثم بين التعامل مع تيار مع أكس واحد وتيار مع ملفات XML متعددة هو العازلة ومنطق الانقسام.

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