如何使用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();
示例字符串
<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();