XML and PHP
Moderator: General Moderators
XML and PHP
So, I have been going through the simpleXML and the DomDocument stuff and while I think I mostly get each part by itself, combining it all has me stumped.
Here is what I am trying to do:
I have a menu tree in xhtml. I want to pull it into a dom document, find a certain list item, and then add a class to all <ul> parents of that list item, then spit back XHTML.
I have created an xpath query which I believe should FIND the right elements to modify (the ul parents) but I have no idea how to now use that selection as a way of altering things
so: xpath://li[@class='current-menu-item']/ancestor::ul
now that I have selected those... how can I apply new attributes to the selected <ul>s? Or am I just going at this all wrong?
Here is what I am trying to do:
I have a menu tree in xhtml. I want to pull it into a dom document, find a certain list item, and then add a class to all <ul> parents of that list item, then spit back XHTML.
I have created an xpath query which I believe should FIND the right elements to modify (the ul parents) but I have no idea how to now use that selection as a way of altering things
so: xpath://li[@class='current-menu-item']/ancestor::ul
now that I have selected those... how can I apply new attributes to the selected <ul>s? Or am I just going at this all wrong?
Re: XML and PHP
what I have tried:
Code: Select all
<?php
$xmlstring= "(a string that is an xml document that I created and is pretty big so I won't post it here)";
$domDocument=new DomDocument('1.0');
$domDocument->loadHTML($xmlstring);
$xpath=new DOMXPath($domDocument);
$xpQuery="//li[@class='current-menu-item']/ancestor::ul"; //gets all the ul ancestors of the selected li.current-menu-item
$results= $xpath->query($xpQuery);
//now we need to get the existing class attribute information and append 'active-parent' to it
foreach ($results as $result) {
$classes=$result->getAttribute('class');
$classes.=' active-parent';
$result->setAttribute($classes);
}
?>
<pre>
<?php echo $domDocument->saveHTML();?>
</pre>
Re: XML and PHP
seems ok to me. What exactly does not work, what results you get?
Edit: you need to specify the attribute name though:
Edit: you need to specify the attribute name though:
Code: Select all
$result->setAttribute('class', $classes);
Re: XML and PHP
yeah, I saw that bug too as I tried running stuff.
Well, the reason it seemed like it wasn't working at all was because it was returning NO values.
I was like.. WTF?
There should be exactly ONE element with current-menu-item as its class. However, it also has OTHER classes, because this is XHTML.
Well.... in XML an element can only have one value for an attribute (class is an attribute) whereas XHTML you can have a BUNCH of classes. So this thing is like <li class="current-page red exploded-squirrel current-menu-item parent-of-bob" id="squiggles"> stuff </li> OK, I made a bunch of those class names up but you get the idea.
I need to be finding the node for which ANY ONE of the values contains current-menu-item
Well, the reason it seemed like it wasn't working at all was because it was returning NO values.
I was like.. WTF?
There should be exactly ONE element with current-menu-item as its class. However, it also has OTHER classes, because this is XHTML.
Well.... in XML an element can only have one value for an attribute (class is an attribute) whereas XHTML you can have a BUNCH of classes. So this thing is like <li class="current-page red exploded-squirrel current-menu-item parent-of-bob" id="squiggles"> stuff </li> OK, I made a bunch of those class names up but you get the idea.
I need to be finding the node for which ANY ONE of the values contains current-menu-item
Re: XML and PHP
AH HAH!
I hope this helps those who come after me. I can only assume this is a common need.
Code: Select all
$xpath="//li[contains(@class,'current-menu-item')]/ancestor::ul"Re: XML and PHP
That would also find elements with classes like 'no-current-menu-item-no-really'rampant wrote:AH HAH!I hope this helps those who come after me. I can only assume this is a common need.Code: Select all
$xpath="//li[contains(@class,'current-menu-item')]/ancestor::ul"
Proper xpath 1.0 for such cases would be
Code: Select all
$xpath = "//li[contains(concat(' ', normalize-space(@class), ' '), ' current-menu-item ')]/ancestor::ul";Re: XML and PHP
ah, good point!
didn't have to worry about that with my particulary application but robust is good.
Couldn't you just use contains(@class, ' current-menu-item ') with the spaces on the ends?
didn't have to worry about that with my particulary application but robust is good.
Couldn't you just use contains(@class, ' current-menu-item ') with the spaces on the ends?
Re: XML and PHP
unfortunately not, because that wouldn't match class="current-menu-item another-class" (no space at the beginning).rampant wrote:Couldn't you just use contains(@class, ' current-menu-item ') with the spaces on the ends?