تجريد تعليقات HTML باستخدام PHP مع ترك الشروط الشرطية

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

سؤال

أستخدم حاليًا PHP وتعبيرًا عاديًا لإزالة جميع تعليقات HTML من الصفحة.السيناريو يعمل بشكل جيد ...قليلا بشكل جيد جدا.إنه يزيل جميع التعليقات بما في ذلك تعليقاتي الشرطية في ملف .وهنا ما لدي:

<?php
  function callback($buffer)
  {
        return preg_replace('/<!--(.|\s)*?-->/', '', $buffer);
  }

  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>

نظرًا لأن التعبير العادي الخاص بي ليس ساخنًا جدًا، فأنا أواجه مشكلة في محاولة معرفة كيفية تعديل النمط لاستبعاد التعليقات الشرطية مثل:

<!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

<!--[if IE 7]>
<link rel="stylesheet" href="/css/ie7.css" type="text/css" media="screen" />
<![endif]-->

<!--[if IE 6]>
<link rel="stylesheet" href="/css/ie6.css" type="text/css" media="screen" />
<![endif]-->

هتافات

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

المحلول

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

وهنا محاولتي في ذلك.لمطابقة التعليقات العادية فقط، قد ينجح هذا.لقد أصبح وحشًا جدًا، آسف لذلك.لقد قمت باختباره على نطاق واسع، ويبدو أنه يقوم بذلك بشكل جيد، لكنني لا أعطي أي ضمان.

<!--(?!\s*(?:\[if [^\]]+]|<!|>))(?:(?!-->).)*-->

توضيح:

<!--                #01: "<!--"
(?!                 #02: look-ahead: a position not followed by:
  \s*               #03:   any number of space
  (?:               #04:   non-capturing group, any of:
    \[if [^\]]+]    #05:     "[if ...]"
    |<!             #06:     or "<!"
    |>              #07:     or ">"
  )                 #08:   end non-capturing group
)                   #09: end look-ahead
(?:                 #10: non-capturing group:
  (?!-->)           #11:   a position not followed by "-->"
  .                 #12:   eat the following char, it's part of the comment
)*                  #13: end non-capturing group, repeat
-->                 #14: "-->"

الخطوات رقم 02 ورقم 11 حاسمة.#02 يتأكد من أن الأحرف التالية لا تشير إلى تعليق شرطي.بعد ذلك، يتأكد #11 من أن الأحرف التالية لا تشير إلى نهاية التعليق، بينما يتسبب #12 و #13 في المطابقة الفعلية.

تقدم بطلبك باستخدام العلامتين "العالمية" و"dotall".

للقيام بالعكس (مطابقة التعليقات الشرطية فقط)، سيكون الأمر كالتالي:

<!(--)?(?=\[)(?:(?!<!\[endif\]\1>).)*<!\[endif\]\1>

توضيح:

<!                  #01: "<!"
(--)?               #02: two dashes, optional
(?=\[)              #03: a position followed by "["
(?:                 #04: non-capturing group:
  (?!               #05:   a position not followed by
    <!\[endif\]\1>  #06:     "<![endif]>" or "<![endif]-->" (depends on #02)
  )                 #07:   end of look-ahead
  .                 #08:   eat the following char, it's part of the comment
)*                  #09: end of non-capturing group, repeat
<!\[endif\]\1>      #10: "<![endif]>" or "<![endif]-->" (depends on #02)

مرة أخرى، قم بالتطبيق باستخدام العلامتين "العالمية" و"dotall".

الخطوة رقم 02 بسبب بناء الجملة "الكشف عن المستوى الأدنى"، راجع: "MSDN - حول التعليقات الشرطية".

لست متأكدًا تمامًا من الأماكن المسموح بها أو المتوقعة.يضيف \s* إلى التعبير حيثما كان ذلك مناسبا.

نصائح أخرى

إذا كنت لا تستطيع الحصول عليها للعمل مع التعبير العادية واحدة أو تجد تريد الحفاظ على المزيد من التعليقات هل يمكن استخدام preg_replace_callback . ويمكنك بعد ذلك تحديد وظيفة للتعامل مع التعليقات على حدة.

<?php
function callback($buffer) {
    return preg_replace_callback('/<!--.*-->/U', 'comment_replace_func', $buffer);
}

function comment_replace_func($m) {
    if (preg_match( '/^\<\!--\[if \!/i', $m[0])) {
        return $m[0];   
    }              

    return '';
}   

ob_start("callback");
?>

... HTML source goes here ...

<?php ob_end_flush(); ?>

في ملخص هذا ويبدو أن الحل الأفضل:

<?php
  function callback($buffer) {
    return preg_replace('/<!--[^\[](.|\s)*?-->/', '', $buffer);
  }
  ob_start("callback");
?>
... HTML source goes here ...
<?php ob_end_flush(); ?>

وويستبعد جميع التعليقات ويترك الشرطية باستثناء رأس واحد:

<!--[if !IE]><!-->
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
<!-- <![endif]-->

وحيث يبدو أن تضاف إلى أن سبب المشكلة.

وإذا كان أي شخص يمكن أن توحي التعبير المعتاد من شأنها أن تأخذ ذلك في الحسبان وترك هذا condtional في مكان ثم أيضا من شأنه أن يكون مثاليا.

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

والشكر

وأنا لست متأكدا مما اذا كان المحرك باستخدام التعابير المنطقية PHP سوف يحبون ما يلي، ولكن حاول هذا النمط:

'/<!--(.|\s)*(\[if .*\]){0}(.|\s)*?-->/'

وشيء من هذا القبيل يمكن أن تعمل:

/<!--[^\[](.|\s)*?-->/

والأمر ذاته الذي تملكه، إلا أنه يتجاهل تصريحات لها قوس مباشرة بعد علامة تعليق البداية.

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