سؤال

لدي مجموعة من المستندات القديمة التي تشبه HTML.كما هو الحال في أنها تبدو مثل HTML، ولكنها تحتوي على علامات إضافية ليست جزءًا من HTML

<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>

أحتاج إلى تحليل هذه الملفات.PHP هي الأداة الوحيدة المتاحة.لا تقترب المستندات من كونها XML جيدة التكوين.

كانت فكرتي الأصلية هي استخدام أساليبloadHTML في PHPs DOMDocument.ومع ذلك، فإن هذه الأساليب تخنق علامات HTML التعويضية، وترفض تحليل السلسلة/الملف.

$oDom = new DomDocument();
$oDom->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
//gives us
DOMDocument::loadHTML() [function.loadHTML]: Tag pseud-template invalid in Entity, line: 1 occured in ....

الحل الوحيد الذي تمكنت من التوصل إليه هو المعالجة المسبقة للملفات بوظائف استبدال السلسلة التي ستزيل العلامات غير الصالحة واستبدالها بعلامة HTML صالحة (ربما امتدادًا بمعرف اسم العلامة).

هل هناك حل أكثر أناقة؟هل هناك طريقة للسماح لـ DOMDocument بمعرفة العلامات الإضافية التي تعتبر صالحة؟هل هناك فئة/كائن تحليل HTML مختلف وقوي لـ PHP؟

(إذا لم يكن الأمر واضحًا، فأنا لا أعتبر التعبيرات العادية حلاً صالحًا هنا)

تحديث:تعد المعلومات الموجودة في العلامات المزيفة جزءًا من الهدف هنا، لذا فإن شيئًا مثل Tidy ليس خيارًا.أيضًا، أنا أبحث عن شيء يؤدي إلى مستوى ما، إن لم يكن كله، من التنظيف الجيد بالنسبة لي، ولهذا السبب كنت أبحث عن طريقة LoadHTML الخاصة بـ DomDocument في المقام الأول.

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

المحلول

يمكنك منع التحذيرات باستخدام libxml_use_internal_errors, ، أثناء تحميل المستند.على سبيل المثال:

libxml_use_internal_errors(true);
$doc = new DomDocument();
$doc->loadHTML("<strong>This is an example of a <pseud-template>fake tag</pseud-template></strong>");
libxml_use_internal_errors(false);

إذا كنت بحاجة، لسبب ما، إلى الوصول إلى التحذيرات، استخدم libxml_get_errors

نصائح أخرى

أتساءل عما إذا كان سيتم تمرير HTML "السيئ" من خلاله HTML مرتب قد يساعد كمرور أول؟قد يكون الأمر يستحق المشاهدة، إذا كان بإمكانك جعل المستند منسقًا بشكل جيد، فربما يمكنك تحميله كملف XML عادي باستخدام DomDocument.

Twan لا تحتاج إلى DTD لـ DomDocument لتحليل XML المخصص.مجرد استخدام DOMDocument->load(), وطالما أن ملف XML منسق بشكل جيد، فيمكن قراءته.

بمجرد أن تصبح الملفات منسقة بشكل جيد، عندها يمكنك البدء في النظر إلى موزعي XML، وقبل ذلك تكون S.O.L.قال لوك أليجو، يمكنك النظر إلى ذلك HTML مرتب, ، ولكن يبدو أن هذا خاص بـ HTML، ولا أعرف كيف ستسير الأمور مع عناصرك المخصصة.

لا أعتبر التعبيرات العادية حلاً صالحًا هنا

حتى تكتسب لياقة بدنية جيدة، فقد يكون هذا هو خيارك الوحيد.بمجرد وصول المستندات إلى تلك المرحلة، تصبح خاليًا من وظائف DOM.

ألق نظرة على المحلل اللغوي في منفذ PHP Fit.الكود نظيف وقد تم تصميمه في الأصل لتحميل HTML القذر المحفوظ بواسطة Word.تم تكوينه لسحب الجداول، ولكن يمكن تعديلها بسهولة.

يمكنك رؤية المصدر هنا:http://gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/Parser.phps

سيوضح لك اختبار الوحدة كيفية استخدامه:http://gerd.exit0.net/pat/PHPFIT/PHPFIT-0.1.0/test/parser.phps

كان الحل السريع والقذر لهذه المشكلة هو تشغيل حلقة تطابق قائمة العلامات المخصصة الخاصة بي مع التعبير العادي.لا يلتقط التعبير العادي العلامات التي تحتوي على علامة مخصصة داخلية أخرى بداخلها.

عندما يكون هناك تطابق، يتم استدعاء وظيفة لمعالجة هذه العلامة وإرجاع "HTML المعالج".إذا كانت هذه العلامة المخصصة داخل علامة مخصصة أخرى، فإن الأصل يصبح بدون أطفال بسبب حقيقة أنه تم إدراج HTML الفعلي بدلاً من العلامة الفرعية، وستتم مطابقته بواسطة regexp ومعالجته في التكرار التالي للحلقة.

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

@ آلان ستورم

تعليقك على إجابتي الأخرى جعلني أفكر:

عندما تقوم بتحميل ملف HTML باستخدام DOMDocument، يبدو أنه يقوم بمستوى ما من التنظيف:جيدة التكوين، ولكنها تتطلب أن تكون جميع علاماتك علامات HTML شرعية.أنا أبحث عن شيء يفعل الأول، ولكن ليس الأخير.(آلان ستورم)

قم بتشغيل regex (عذرًا!) على العلامات، وعندما يعثر على عنصر ليس عنصر HTML صالحًا، استبدله بعنصر صالح تعرف أنه غير موجود في أي من المستندات (blink يتبادر إلى ذهنك...)، وأعطه قيمة سمة باسم العنصر غير القانوني، بحيث يمكنك تبديله مرة أخرى بعد ذلك.على سبيل المثال:

$code = str_replace("<pseudo-tag>", "<blink rel=\"pseudo-tag\">", $code);
// and then back again...
$code = preg_replace('<blink rel="(.*?)">', '<\1>', $code);

من الواضح أن هذا الرمز لن يعمل، ولكن هل فهمت الفكرة العامة؟

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