Как эффективно сопоставить ID и href с помощью PHP?

1

Пример строки

<a href="#fn2" class="fn-ref" id="s9781473910270.i12">
<a href="#fn3" class="fn-ref" id="s9781473910270.i13">

<a class="ref-fn-ref" href="#fn2"></a>
<a class="ref-fn-ref" href="#fn3"></a>

Ожидаемый результат

<a href="#fn2" class="fn-ref" id="s9781473910270.i12">
<a href="#fn3" class="fn-ref" id="s9781473910270.i13">

<a class="ref-fn-ref" href="#s9781473910270.i12"></a>
<a class="ref-fn-ref" href="#s9781473910270.i13"></a>

Чтобы получить ожидаемый результат, у меня есть общая строка в обоих якорях: href=#fn чтобы я мог сопоставлять оба якоря. Если оба hrefs одинаковы в обоих якорях, тогда идентификатор привязки class="ref-fn-ref" должен быть заменен идентификатором привязки class="fn-ref".

Я пытался,

preg_match_all("/<a href=\"#fn([0-9]+)\"\\s*class=\"fn-ref\"\\s*id=\"(.*?)\">/s",$r,$match1);
//captured the first anchor href no. and ID  

preg_match_all("/<a\\s*class=\"ref-fn-ref\"\\s*href=\"#fn([0-9]+)\"/s",$r,$match2);
//captured the second anchor href no. 

for($i=0;$i<count($match1[0]);$i++){
    for($j=0;$j<count($match2[0]);$j++){
        if($match1[1][$i]===$match2[1][$j]){
//if both href same then replace First anchor ID with second

    $tochange=preg_replace("/href=\".*?\"/s","href=\"#".$match1[2][$i]."\"",$match2[0][$j]);
    $r=str_replace($match2[0][$j],$tochange,$r);
        }}}

echo $r;

Вывод

<a href="#fn2" class="fn-ref" id="s9781473910270.i12">
<a href="#fn3" class="fn-ref" id="s9781473910270.i13">
<a class="ref-fn-ref" href="#s9781473910270.i12"></a>
<a class="ref-fn-ref" href="#s9781473910270.i13"></a>

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

  • 2
    Не используйте регулярные выражения для анализа HTML, используйте синтаксический анализатор HTML / XML.
  • 0
    почему вы не идете на JavaScript или JQuery ???
Показать ещё 2 комментария
Теги:
string
preg-match-all

1 ответ

2
Лучший ответ

Поскольку у вас есть структурированные данные, вы должны использовать эту структуру, вот базовый пример с полезными методами DOM:

$dom = new DOMDocument;
$dom->loadHTML($html);

$linkNodes = $dom->getElementsByTagName('a');

foreach ($linkNodes as $linkNode) {
    if ($linkNode->hasAttribute('href') && $linkNode->hasAttribute('id'))
        echo $linkNode->getAttribute('href') . PHP_EOL .
             $linkNode->getAttribute('id') . PHP_EOL . PHP_EOL;
}

Для ваших конкретных требований вы можете использовать что-то вроде этого:

$dom = new DOMDocument;
$dom->loadHTML($html);

$linkNodes = $dom->getElementsByTagName('a');

// first you collect references and target links in two arrays
$refs = []; // associative array with ref as key and id as value
$targets = []; // each item is an array with href value and the node itself

foreach ($linkNodes as $linkNode) {
    $href = $linkNode->getAttribute('href');

    if ($linkNode->getAttribute('class') === 'fn-ref')
        $refs[$href] = $linkNode->getAttribute('id');
    elseif ($linkNode->getAttribute('class') === 'ref-fn-ref')
        $targets[] = [$href, $linkNode];
}

// then you only need to loop over targets, check if the reference exists in $refs,
// and change the href attribute with the corresponding id value.
foreach ($targets as $target) {
    if (isset($refs[$target[0]]))
        $target[1]->setAttribute('href', '#' . $refs[$target[0]]);
}

echo $dom->saveHTML();
  • 0
    Это отлично. Но как я могу сопоставить два hrefs и заменить ID?
  • 0
    @Vidhya: я добавил пример для ваших требований.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню