James
James

Reputation: 43647

Move title attribute value to class attribute value in the HTML code

We have variable $menu with HTML inside (there is no loop, it comes from a function).

On echo it gives the code like this:

<ul id="menu">
    <li id="some-id" class="many classes"><a title="one" href="#">text</a></li>
    <li id="some-id" class="many classes"><a href="#">text</a></li>
    <li id="some-id" class="many classes"><a title="three" href="#">text</a></li>
</ul>

What I want to do:

  1. get value of the title="" of each link, and move it to the end of parent <li> class.

  2. remove title="" from each link.

Code inside variable $menu should become:

<ul id="menu">
    <li id="some-id" class="many classes one"><a href="#">text</a></li>
    <li id="some-id" class="many classes"><a href="#">text</a></li>
    <li id="some-id" class="many classes three"><a href="#">text</a></li>
</ul>

What is the solution?

Upvotes: 1

Views: 743

Answers (4)

Chetan
Chetan

Reputation: 48001

Use this regex:

(<li[^>]*class=".*)("><a).*title="(.*)"(.*)

And replace each match using backreferences:

\1 \3\2\4

Note that this will work for your example, but you might need to modify it and make it "smarter" if you have cases such as:

<li id="some-id >" class="many classes"><a title="one" href="#">text</a></li>

Upvotes: 1

Gordon
Gordon

Reputation: 316969

Same as with your other question. Use DOM:

$dom = new DOMDocument;
$dom->loadXML( $html );
$xpath = new DOMXPath( $dom );
$links = $xpath->query( '/ul/li/a[@title]' );
foreach($links  as $link ) {
    $classes  = $link->parentNode->getAttribute( 'class' );
    $classes .= ' ' . $link->getAttribute( 'title' );
    $link->parentNode->setAttribute( 'class', $classes );
    $link->removeAttribute( 'title' );
}
echo $dom->saveXML( $dom->documentElement );

Again, this assumes you are using valid XHTML. If not, you have to load the markup with loadHTML and change the XPath to take the added HTML skeleton into account. Be aware that this also changes what documentElement of the DOMDocument, so you have to pass the menu node to saveXML instead.

Upvotes: 0

Naveed
Naveed

Reputation: 42093

You can use PHP Simple HTML DOM Parser to modify your HTML:

In your case if no of li are fixed in $menu then you do something like this with Simple HTML DOM Parser:

// Include downloaded library
include 'simplehtmldom/simple_html_dom.php';

// Create DOM from string
$html = str_get_html( $menu );


for( $i=0 ; $i<3 ; $i++ ) {

    // Get current classes of li
    $currentClasses = $html->find('li', $i)->class;

    // Get title of link
    $linkTitle = $html->find('a', $i)->title;

    // Add link title in li classes
    $html->find('li', $i)->class = $currentClasses . ' ' . $linkTitle ;

    // Remove title attribute from link
    $html->find('a', $i)->title = null;
}


echo $html;

Upvotes: 1

Luke Stevenson
Luke Stevenson

Reputation: 10341

It's not a perfect solution, but it has worked in my testing (Regex Buddy & XAMPP) with your sample code.

$pattern = '/(<li [^>]*)(?:class=(?:"([^"]+)"|\'([^\']+)\'))([^>]*><a[^>]*)(?:title=(?:"([^"]+)"|\'([^\']+)\'))\s([^>]*>)(.*?<\/li>)/im';
$replace = '$1class="$2 $5"$4$7$8';

preg_replace( $pattern , $replace , $menu );

Upvotes: 1

Related Questions