echo $ul; // gives this code:
<ul id="menu">
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class">...</li>
</ul>
如何为第一个和最后一个<li>
添加一些课程?
需要正则表达式解决方案。
echo $ul;
应该给出(如果我们为最后一个my_class
添加了课程<li>
):
<ul id="menu">
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class my_class">...</li>
</ul>
答案 0 :(得分:37)
DOM解决方案
$dom = new DOMDocument;
$dom->loadHTML( $ul );
$xPath = new DOMXPath( $dom );
$xPath->query( '/html/body/ul/li[last()]/@class' )
->item( 0 )
->value .= ' myClass';
echo $dom->saveXml( $dom->getElementById( 'menu' ) );
如果您知道HTML有效,您也可以使用loadXML
。这将使DOM不再添加HTML骨架。请注意,您必须将XPath更改为'/ul/li[last()]/@class'
。
如果您不熟悉XPath查询,还可以使用常规DOM接口,例如
$dom = new DOMDocument;
$dom->loadHTML( $ul );
$liElements = $dom->getElementsByTagName( 'li' );
$lastLi = $liElements->item( $liElements->length-1 );
$classes = $lastLi->getAttribute( 'class' ) . ' myClass';
$lastLi->setAttribute( 'class', $classes );
echo $dom->saveXml( $dom->getElementById( 'menu' ) );
编辑由于您已将问题更改为第一个和最后一个类,因此以下是使用XPath执行此操作的方法。这假设您的标记是有效的XHTML。如果没有,请切换回loadHTML
(请参阅上面的代码):
$dom = new DOMDocument;
$dom->loadXML( $html );
$xpath = new DOMXPath( $dom );
$first = $xpath->query( '/ul/li[1]/@class' )->item( 0 );
$last = $xpath->query( '/ul/li[last()]/@class' )->item( 0 );
$last->value .= ' last';
$first->value .= ' first';
echo $dom->saveXML( $dom->documentElement );
答案 1 :(得分:9)
或者,您可以在CSS中使用“#menu li:last-child
”而不是类名,这样您就不必修改PHP代码。
答案 2 :(得分:4)
如果您必须为此使用正则表达式(不完全是建议)。 我认为这应该有用......
$replacement1 = "<li\s.*?class="(.*?)".*?>.*?</li>\s</ul>";
$string1 = "$1 class_last";
$ul = preg_replace($ul, $replacement1, $string1);)
$replacement2 = "<ul.*?>\s<li\s.*?class="(.*?)".*?>";
$string2 = "$1 class_first";
$ul = preg_replace($ul, $replacement2, $string2);)
答案 3 :(得分:3)
如果你真的想用正则表达式做这个工作,你可以尝试:
$ul = '
<ul id="menu">
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class">...</li>
</ul>
';
// explode input string to an array
$lines = explode("\n", $ul);
$found_first = 0; // is the first li founded
$found_last = 0; // index of the last li
$class_first = "class_first"; // class for the first li
$class_last = "class_last"; // class for the last li
// loop on all lines
for ($i = 0; $i < count($lines); $i++) {
$line = $lines[$i];
// the line begins with <li
if (preg_match("/^<li/", $line)) {
// is it the first one
if (!$found_first) {
// add the class
$lines[$i] = preg_replace('/ class="([^"]+?)"/', " class=\"$1 $class_first\"", $lines[$i]);
// the first li have been found
$found_first = 1;
}
// memo the last line proceded
$found_last = $i;
}
}
// this will add class_last even if the last li
// is also the first one (ie: only one li)
if ($found_last) {
$lines[$found_last] = preg_replace('/ class="([^"]+?)"/', " class=\"$1 $class_last\"", $lines[$found_last]);
}
$ul = implode("\n", $lines);
echo $ul;
输出继电器:
<ul id="menu">
<li id="some_id" class="some_class class_first">...</li>
<li id="some_id" class="some_class">...</li>
<li id="some_id" class="some_class class_last">...</li>
</ul>
答案 4 :(得分:3)
您可以使用计数器:
<?php
$list = array('aaa', 'bbb', 'ccc', 'ddd');
$items = count($list); // count items in list
$i = 1; // set counter to one, because first item in list will be item number: 1
echo '<ul>';
// create loop
foreach($list as $value) {
// first item
if($i == 1) {
$class = 'some_class first_class';
// last item
} elseif ($i == $items) {
$class = 'some_class last_class';
// not first / not last item
} else {
$class = 'some_class';
}
echo '<li id="some_id" class="'. $class .'">' . $value . '</li>';
$i++; // raise $i by one
}
echo '</ul>';
?>
将输出:
<ul>
<li id="some_id" class="some_class first_class">aaa</li>
<li id="some_id" class="some_class">bbb</li>
<li id="some_id" class="some_class">ccc</li>
<li id="some_id" class="some_class last_class">ddd</li>
</ul>
但是,我的建议是:
<ul id="menu">
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
<li>ddd</li>
</ul>
在你的CSS中:
#menu {
}
#menu li:first-child {
}
#menu li {
}
#menu li:last-child {
}