Reputation: 1672
I've been going back through all my old code and trying to optimize it. Something I recently stumbled across and that has gotten me stumped is trying to find an xpath solution for this:
function findit($search) {
$i=0;
foreach($xml as $page) { //loop to find specific $element based on $attribute
if($page['src']==$search) { return $i; }
$i++;
}
}
Needs to return $i
so that it can be used for reference to the element in the XML later.
It seems like it should be possible, and I've found a few xpath strings that seem like they should work, but don't. They usually refer to preceding-children
and counting them through the xpath()
function, but I can't find the original sources anymore and don't how to translate that to a PHP xpath string.
Is this even possible? Or is it any better/faster/efficient than what I've already got? Suggestions/Solutions?
EDIT: For Tandu's Solution
Example of my XML File
<range>
<page src="attribute1" />
<page src="attribute2" />
etc...
<page src="attribut20" />
</range>
In my current PHP function, $i
always returns 0
but should return whatever position $search
is found at. Edited so it no longer needs to convert simplexml.
function findit($search) {
$dom=new DOMDocument('1.0');
$dom->load($file);
$xpath=new DOMXPath($dom);
$i=$xpath->evaluate("count(/range/page[@src='$search']/preceding-sibling::*)");
die($dom->saveXML());
}
Upvotes: 5
Views: 728
Reputation: 243599
Use a single XPath expression, so you don't need to iterate the result:
elementWithSomeName[@attribute = 'someNeededValue']
or (in case "attribute is a name of an element):
elementWithSomeName[attribute = 'someNeededValue']
Upvotes: 0
Reputation: 191819
PHP has at least two (that I know of) methods for handling Xpath: the DOMXPath library, which works with DOMDocument, and SimpleXML, which has its own xpath()
method. If you want to evaluate actual expressions (such as getting the i in your example), you have to use DOMXPath::evaluate()
. SimpleXML::xpath()
will only return a node list (as will DOMXPath::query()
. There are also xpath_
methods in php, but these seem to be functional versions of the other methods and still require DOM context node objects.
I'm not sure what the xml
in your example above is, but the example below uses DOMXPath. That I know of, there is no simple way to convert SimpleXML
to DOMDocument
. You'll just have to load the xml separately.
$xml = <<<XML
<root>
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
<child attribute="two" />
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
<child attribute="one" />
</root>
XML;
$dom = new DOMDocument;
$dom->loadXML($xml);
//DOMXPath requires DOMDocument in its constructor
$xpath = new DOMXPath($dom);
//evaluate will return types .. we are expecting an int, not a DOMNodeList
//Look for a child node of root named "child" with attribute="two"
//Count all its preceding siblings.
$i = $xpath->evaluate('count(/root/child[@attribute="two"]/preceding-sibling::*)');
Upvotes: 3