如何使用PHP有效匹配ID和href?

How to match ID and href in an effective way using PHP?

示例字符串

<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 以便我可以匹配两个锚点。如果两个 href 在两个锚点中都相同,那么 class="ref-fn-ref" 锚点的 ID 应该替换为 class="fn-ref" 锚点的 ID。

我试过了,

preg_match_all("/<a href=\"#fn([0-9]+)\"\s*class=\"fn-ref\"\s*id=\"(.*?)\">/s",$r,$match1);
//captured the first anchor's 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's 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's same then replace First anchor's 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>

正在获得预期的输出。但是仍然会有一种最简单的方法来做到这一点,只是我需要知道如何以其他方式完成它?我希望它会被理解。

既然你有结构化数据,你应该使用这个结构,这里有一个基本的例子,有有用的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();