Вытащить текст до определенной метки

Статус
В этой теме нельзя размещать новые ответы.

GEEPERS

Знаток
Регистрация
26 Янв 2008
Сообщения
162
Реакции
25
Нужно вытащить текст от начала до первого тега (тег неизвестен) и от последнего закрывающего тега (он необязательно должен быть парой первого) - до конца текста. Если текст всередине не заключен ни в какие теги, его тоже надо сграбитъ.

Схематически можно представитъ:
HTML:
<body>{Текст А}<some_tag>Текст Тега</some_tag>{Текст Б}<some_tag>Текст Тега</some_tag>{Текст В}</body>
- нужно вытащить только текст <body>: {Текст А},{Текст Б},{Текст В}.
Еще неплохо бы было учесть теги, несодержащие закрывающего тега.
думаю через preg_match_all вытащить:
PHP:
preg_match_all( '$reg_exp', $body, $body_part, PREG_SET_ORDER );
Помогите регулярку составить:thenks:
 
Нужно вытащить текст от начала до первого тега (тег неизвестен) и от последнего закрывающего тега (он необязательно должен быть парой первого) - до конца текста. Если текст всередине не заключен ни в какие теги, его тоже надо сграбитъ.
Если так, получается в примере должно выбрать две пустых строки. Или теги body не учитывать?
 
ну да, как раз из <body> то мне и нужно.

PHP:
$reg='~^[a-z].*?/<(/?[^\>]+)\>.*?\Z~si';
- не работает. Что не так?
 
Вот:
PHP:
<?php
$attrs='\b(?: \s*\b\w+\s*=\s*(?:"[^"]*"|\'[^\']*\'|[^<>\s"\']+) )*+  \s*+ /?+';

$singletag='(?:BASEFONT|BR|AREA|LINK|IMG|PARAM|HR|INPUT|COL|FRAME|ISINDEX|BASE|META)';

$blocktag='(?:P|DL|DIV|CENTER|NOSCRIPT|NOFRAMES|BLOCKQUOTE|FORM|ISINDEX|HR|TABLE|FIELDSET|ADDRESS|UL|OL|DIR|MENU|PRE|H[1-6])';

$re="{
((?:[^<>]++|.)*?)
(?:
		<$singletag$attrs>
	|
		<p$attrs>.*?(?= <$blocktag$attrs>|$)
	|
		(<(\w+)$attr>
		(?:
		        [^<>]++|
		        (?-2)|
		        .
		)*?
		(?:</\g{-1}\s*>|$))
	|
		$
)
}six";

$text = '<body>t1<span>qwe</span>t2<i>qwe</i>t3<img>t4<p>qwe<div>asdsd</div>t5<div>qwe<div>www</div>asd</div>t6</body>';

$text=preg_replace("{<body$attrs>(.*)</body>}six", '$1', $text);
preg_match_all($re, $text, $m);

print_r($m[1]);
 
ты забыл добавить <а> в блоковые теги. Я у себя просто вставил "|А|", но не работает. Точнее, не совсем так работает.
Вот что возвращает при поиске такого кода:

HTML:
this is a line of text in the body
<p id="main">this is a paragraph whose parent <a href="#">is the body</a></p>
<a href="http://">this is a link whose parent is the body</a> middle text in the body 
<a href="http://w3.org">this is a second link whose parent is the body</a> 
<p>this is a second paragraph whose parent is the body</p>
this is more body text
Возврат:
HTML:
Array
(
    [0] => 
this is a line of text in the body

    [1] => <a href="#">is the body</a></p>
<a href="http://">this is a link whose parent is the body</a> middle text in the body 
<a href="http://w3.org">this is a second link whose parent is the body</a> 

    [2] => 
)
- (здесь я показал теги для удобства).

Подозреваю, что кроме |A| надо еще где-то исправить?
 
Не, тег <a> в блоковые добавлять не надо. Разные теги, завершающие абзац, добавил а самое очевидное - закрывающий тег - забыл добавить:)
Код:
$re="{
((?:[^<>]++|.)*?)
(?:
        <$singletag$attrs>
    |
        <p$attrs>.*?(?: </p\s*> | (?= <$blocktag$attrs>) | $)
    |
        (<(\w+)$attr>
        (?:
                [^<>]++|
                (?-2)|
                .
        )*?
        (?:</\g{-1}\s*>|$))
    |
        $
)
}six";
 
все же необходимо немного дополнить твой код;), т.к. если текст окружают <а> теги, они парсятся вместе с нужным текстом. Ну тут даже я разобрался: просто добавил
PHP:
| <a$attrs>.*?(?: </a\s*> | (?= <$blocktag$attrs>) | $)
P.S.: если не тяжело, добавь плз. комментарии к своему коду, или отдельно опиши детали. А то вобщем смысл понятен, а что конкретно...
Думаю другим начинающим тоже будет полезно.:)
 
С комментариями:
PHP:
<?php
$attrs='\b(?: \s*\b\w+\s*=\s*(?:"[^"]*"|\'[^\']*\'|[^<>\s"\']+) )*+  \s*+ /?+'; //кусок регулярки, совпадает с атрибутами тега, все что от его названия до '>'

$singletag='(?:BASEFONT|BR|AREA|LINK|IMG|PARAM|HR|INPUT|COL|FRAME|ISINDEX|BASE|META)'; //список одиночных тегов

$blocktag='(?:P|DL|DIV|CENTER|NOSCRIPT|NOFRAMES|BLOCKQUOTE|FORM|ISINDEX|HR|TABLE|FIELDSET|ADDRESS|UL|OL|DIR|MENU|PRE|H[1-6])'; //список блочных тегов. Используется для определения конца абзаца <p>. Например  ...<p>(...)<p>...

$re="{
((?:[^<]++|.)*?) #Все, что не является тегом. Символы [^<] захватываются по максимому, символы < только если не являются частью тега. Результат сохраняется.
(?:  #Если мы здесь, значит наткнулись на смивол <, либо пришли к концу строки. Далее список альтернатив:
        <$singletag$attrs>  #Одиночный тег
    |
        <p$attrs>.*?(?: </p\s*> | (?= <$blocktag$attrs>) | $) #тег <p>. Он заканчивается либо </p>, либо перед началом одного из тегов \$blocktag, либо в конце строки
    |
        <(\w+)$attr> #Любой другой тег. Название тега запоминаем. Внутри тега могут быть:
        (?:
                [^<]++| #no comments
                (		#Такой же тег. Вернее пара открывающий/закрывющий тег.
				<\g{2}$attr>
					(?: #Внутри может быть:
						[^<]++| #опять no comments
						(?-1)|  #Вложеннаая пара таких же тегов. Применяем кусок регулярки с 18 по 25 строку опять
						. #остальное
					)*?
				(?:</\g{2}\s*>|$) #Завершается либо закрывающим тегом, либо в конце строки
				)| 
                . #остальное
        )*?
        (?:</\g{2}\s*>|$) #Завершается либо закрывающим тегом, либо в конце строки
    |
        $ #Ну и последняя альтернатива первого уровня - конец строки
)
}six";

$text = '<body>t1<span>qwe</span>t2<i>qwe</i>t3<img>t4<p>qwe<div>asdsd</div>t5<div>qwe<div>www<div>www<div>www</div></div></div>asd</div><ul><li>asd</ul>t6</body>';

$text=preg_replace("{<body$attrs>(.*)</body>}six", '$1', $text); //Удаляем теги <body>, если они есть
preg_match_all($re, $text, $m);

print_r($m[1]);
все же необходимо немного дополнить твой код, т.к. если текст окружают <а> теги, они парсятся вместе с нужным текстом. Ну тут даже я разобрался: просто добавил
Когда комментировал нашел ошибку. Проверь, теперь должно все работать.
 
по крайней мере к данному примеру данный код подходит
PHP:
$string = '<body>{Текст А}<some_tag>Текст Тега</some_tag>{Текст Б}<some_tag>Текст Тега</some_tag>{Текст В}</body>';

preg_match_all("/<body>(.+?)<\/body>/si", $string, $match); // поиск всего в тегах body, включая сам тег
preg_match_all("/(.+?)<[^>]*>/s", $match[0][0], $matches); // $match[1][0] - в найденом ищется любой текст, после которого есть любой тег(открывающийся или закрывающийся)
$arr = array();
foreach($matches[0] as $matches2){
	if(!preg_match("/<\/[^>]*>/si", $matches2) || preg_match("/<\/body>/si", $matches2)){ // если нет закрывающегося тега или это не body - трем тег и получаем текст в чистом виде 
		array_push($arr, preg_replace("/<[^>]*>/si","",$matches2));
	}
}
print_r($arr);
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху