سؤال

أحاول استرداد علامات محددة مع محتواها من وثيقة XHTML، لكنها تتطابق مع علامات النهاية الخاطئة.

في المحتوى التالي:

<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>

تتم مطابقة علامة Content_Block End Tag for ID = "Welcome" في الواقع كعلامة المنتهية لأول علامة Content_Block الأولى.

Regex أنا أستخدمها هي:

/<content_block id="(.*)">([\w\W]*?)<\/content_block>/i

أي مؤشرات حول المكان الذي فشلت فيه؟

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

المحلول

... والإجابة هي نفسها دائما لا يمكن القيام ب HTML + Regex. وبعد آسف. استخدم مكتبة تحليل HTML لإطارك الخاص. أو، إذا كانت وثيقتك مضمونة فقط تحتوي فقط على XHTML صالحة، خذ نهج XPath كما هو مقترح بواسطة Jitter في تعليق.

نصائح أخرى

قد يساعد ذلك في العثور على البرنامج التعليمي http://www.regular-expressions.info/examples.html.الذي يذكر التقاط زوج من السلسلة المتكررة في نص معين. الاقتراح هو استخدام؟ بعد. * لجعلها تتوقف بعد الحدوث الأول لإنهاء سلسلة الزوج في النص

هذه مشكلة معروفة مع Regex - لا يمكنك مطابقة أزواج. مطابقة إما الجشع، حيث تتطابق مع الأخير الذي يجد، أو غير جشع، حيث يطابق فيها الأول. لا يمكنك إقناع Regex بتحديد الأقواس الافتتاحية والإغلاق.

أود أن أوصي بتحميلها في دوم واستخدام ذلك. إذا كنت تحاول تنفيذ محلل HTML، فسوف أوصي باستخدام Regex إلى Lex IT، ثم المحللين الأيمن اليمنى لتحليل إخراج Lexer الخاص بك.

بفضل @ جان żankowski. و @ تشيغامي, ، أعطاني إجابتهم الأحجام

اسمحوا لي أن أستخدم PHP لإظهار التعليمات البرمجية

<?php
$xml = <<<EOT
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOT;

preg_match('/<cache_namespace[^>]+>((?:(?!(<\/?div>)).)*)<\/cache_namespace>/s', $xml, $matches);
print_r($matches);

ريجيكس ملاحظة

  • s الخيار: . في النموذج يطابق جميع الشخصيات، بما في ذلك خطوط نيو
  • المفتاح هنا هو ذلك (?:(?!STRING).)* هو السلاسل كما [^CHAR]* هو الشخصيات

نتيجة

Array
(
    [0] => <cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
    [1] => 
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>

)

تحليل XHTML أو XML ليس بالأمر الصعب. افترضت أن لديك رمز صالح أو شكل جيد.

#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $xml = <<"EOF";
<cache_namespace name="content">
    <content_block id="15">
    some content here

        <cache_namespace name="user">
            <content_block id="welcome">
            Welcome Apikot!
            </content_block>
        </cache_namespace>
    </content_block>
</cache_namespace>
EOF

while ($xml =~ m!
<(content_block)\sid="welcome"> # Start tag definition.
 (\s*                           # It may consists of
   (?: <\!--.*?-->              # - comment
   |  [^<]*                     # - text
   |  <[^>]+/>                  # - another closed tag
   |  <\s*(\w+)[^>]*>           # - another tag with some content
       (?2)+                    # (recursive definition of possible tag content)
      </\3>
   )
 )*
</\1>
!sxgc) {
    print "==> $&\n\n";
}

يرجى تعديل تعريف العلامة البدء لمحتوى آخر (مثل <\s*(\w+)[^>]*+>). على أي حال، إنها نقطة بداية جيدة.

إذا لم تستخدم Recursion (خط مع (?2)+) سوف تمسك هذه الأمثلة. وبعد هذا الرمز يمكن التعامل معهم جميعا (يرجى النظر هنا قبل) أو يمكن بسهولة التكيف مع المواقف الجديدة.

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