Попытка найти тег и получить атрибуты с помощью регулярных выражений в PHP - PullRequest
0 голосов
/ 22 сентября 2019

Я сделал регулярное выражение в php, чтобы найти тег и атрибуты в строке html.Это работает, но работает только с первым атрибутом, а не повторяется.Следующий код возвращает мне первый атрибут и значение.

'@<barcode(\s([a-z]+)="([^"]+)").*/>@m'

Итак, я добавил плюс, чтобы он повторился, но он не будет работать.

'@<barcode(\s([a-z]+)="([^"]+)")+.*/>@m'

Что происходит последобавление плюса в том, что он выбирает только последний атрибут и значение.

Мне просто нужны все атрибуты и значения в массиве, поэтому мне интересно, что я делаю неправильно.Вот возможный HTML, который я ищу.Иногда атрибуты не всегда нужны, поэтому я должен принять это во внимание.

<barcode type="C128B" height="10" fontsize="0.4" code="testcode" align="L"/>
<barcode type="Hello"/>
<barcode type="Hello" code="balls"/>
<barcode type="C128B" height="10" fontsize="0.7" code="test" align="L"/>

У меня есть пример на regex101, чтобы увидеть проблему https://regex101.com/r/jMdA6S/1

Наше текущее приложение работает, но толькоповторяя следующие строки

'@<barcode ([a-z]+)="(.*)" ([a-z]+)="(.*)" ([a-z]+)="(.*)" ([a-z]+)="(.*)" ([a-z]+)="(.*)".*/>@m'

Это означает, что каждый раз, когда я добавляю новый атрибут, я должен добавлять еще один блок кода в регулярное выражение.Я пытаюсь избежать этого, поскольку нам иногда приходится добавлять новый атрибут для добавления различных функций.

Ответы [ 4 ]

1 голос
/ 22 сентября 2019

Хорошей практикой является анализ содержимого HTML с помощью соответствующего манипулятора .По вашему вопросу вы можете выполнить синтаксический анализ во время чтения файла (подход SAX) или загрузить файл за один раз, а затем получить доступ к его содержимому (подход DOM).

Вот a способ выполнить то, что вам нужно.Мне нравится использовать способ SAX, если мне не нужно сохранять весь контент (широко на основе Пример структуры XML-элемента официального сайта PHP):

<code><?php
$file = "data.html"; // your file
$depth = array();

function startElement($parser, $tagname, $attrs)
{
    // For each tag encountered
    //   - $tagname contains the name
    //   - $attrs is an associative array name -> value of the attributes

    // Add the code below the code to deal with it:
    echo "<pre>\n";
    echo "Tags : $tagname\n";
    echo "Attributes:\n";
    print_r($attrs);
    echo "
\n ";} // Создать анализатор $ xml_parser = xml_parser_create (); // Установить дескрипторы элементов для анализатора (нам просто нужен обработчик начального элемента, // поэтому конечный элемент устанавливается как FALSE xml_set_element_handler ($ xml_parser," startElement ", FALSE); // Откройте ваш файл if (! ($ Fp = fopen ($ file, "r"))) {die ("Oops.");} // Циклическое чтение и анализ файла в то время как ($ data =fread ($ fp, 4096)) {if (! xml_parse ($ xml_parser, $ data, feof ($ fp))) {die ("Упс.");}} // Готово. Освободите ваш анализатор. xml_parser_free ($ xml_parser);?>
1 голос
/ 22 сентября 2019

Вам нужно поставить /g в конце вашего регулярного выражения, например:

<barcode(\s([a-z]+)="([^"]+)").*/g>
0 голосов
/ 24 сентября 2019

Ну, хотя были некоторые хорошие ответы, никто не смог мне сказать, есть ли способ сделать это в одном регулярном выражении, каков был мой вопрос.Однако мне пришлось уступить и сделать это в двух регулярных выражениях. Я пытался избежать двух регулярных выражений, так как я думал, что плюс должен повторять среднюю часть.

Первый регулярный поиск находит теги, и у меня естьфункция getAttributes, которая получает атрибуты.Затем функция getAttributes помещает каждый в плоский массив для обработки.Я даю ответ, но даже этот ответ на самом деле не отвечает на мой вопрос о том, как это сделать за одно регулярное выражение.Однако я опубликую то, что у меня получилось, если это кому-нибудь поможет.

И Амессихель, и Мачей Кроль дали хороший совет, и я бы, вероятно, воспользовался этим советом, если бы строился новый проект.Однако я пошел со следующим кодом:

<code><?php
$str = '<barcode type="C128B" height="10" fontsize="0.4" code="pdfbarcode_content" align="L"/>
<barcode href="Hello"/>
<barcode href="Hello" type="balls"/>
<barcode type="C128B" height="10" fontsize="0.4"/>
<barcode type="C128B" height="10" fontsize="0.4" code="test" align="L"/>';

function getAttributes($attr){  
    preg_match_all('@(?:([a-z]+)="([^"]+)")+@m', $attr, $matches,PREG_SET_ORDER);
    $rArray=[];
    foreach($matches as $line):
        array_push($rArray,$line[1]);
        array_push($rArray,$line[2]);
    endforeach;
    return $rArray;
}
function barcode($file){
    return preg_replace_callback(
        '@<barcode(.*)/>@m',
        function($matches) {
            echo '<pre>'.print_r($matches[1],1).'
';echo '
'.print_r(getAttributes($matches[1]),1).'
';echo "-----------------------";// Здесь я обрабатываю массив return '';}, $ file);} штрих-код ($ str);
0 голосов
/ 22 сентября 2019

Вам, вероятно, нужно написать парсер для этого, если вы хотите сопоставить неограниченное количество объектов xml и получить доступ к парам значений ключей из них (используя регулярное выражение).

Я подготовил для вас рабочий пример.

   $offset = 0;

   $lines = '
       <barcode type="C128B" height="10" fontsize="0.4" code="testcode" align="L"/>
       <barcode type="Hello"/>
       <barcode type="Hello" code="balls"/>
       <barcode type="C128B" height="10" fontsize="0.7" code="test" align="L"/>
   ';

   while (preg_match('/<(\S*)[\s]*(.*)[\s]*\/>/', $lines, $line_matches, PREG_OFFSET_CAPTURE, $offset))
   {
       // Set offset to the next line
       $offset = $line_matches[0][1] + strlen($line_matches[0][0]);

       // Get the line name
       $name = $line_matches[1][0];

       // Get the line content
       $line_content = $line_matches[2][0];

       if(preg_match_all('/([a-z]+)="([^"]+)"/', $line_content, $key_values_matches))
       {
           // Access all matched keys
           $keys = $key_values_matches[1];

           // Access all matches values
           $values = $key_values_matches[2];

           foreach ($keys as $index => $key) {
               // Access matched value for key
               $value = $values[$index];

               // Do something with your match
               echo "Found match in \"{$name}\" for key \"{$key}\" with value \"{$value}\"\n";
           }
       }

   };
...