Найти конкретный элемент на основе атрибута - PullRequest
5 голосов
/ 27 октября 2011

Я перебираю весь свой старый код и пытаюсь его оптимизировать. Что-то, с чем я недавно столкнулся и которое поставило меня в тупик, пытается найти решение xpath для этого:

function findit($search) {
    $i=0;
    foreach($xml as $page) { //loop to find specific $element based on $attribute
       if($page['src']==$search) { return $i; }
       $i++;
    }
}

Необходимо вернуть $i, чтобы его можно было использовать для ссылки на элемент в XML позже.

Кажется, это должно быть возможно, и я нашел несколько строк xpath, которые, похоже, должны работать, но не работают. Обычно они ссылаются на preceding-children и подсчитывают их через функцию xpath(), но я больше не могу найти исходные источники и не могу перевести это в строку PHP xpath.

Это вообще возможно? Или это лучше / быстрее / эффективнее, чем у меня уже есть? Предложения / решения?

РЕДАКТИРОВАТЬ: Для решения Танду

Пример моего XML-файла

<range>
    <page src="attribute1" />
    <page src="attribute2" />
    etc...
    <page src="attribut20" />
</range>

В моей текущей PHP-функции $i всегда возвращает 0, но должен возвращать любую найденную позицию $search. Отредактировано так, что больше не нужно конвертировать 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());
}

Ответы [ 2 ]

3 голосов
/ 27 октября 2011

PHP имеет как минимум два (насколько мне известно) метода для обработки Xpath: библиотека DOMXPath , которая работает с DOMDocument и SimpleXML имеет собственный метод xpath(). Если вы хотите оценить фактические выражения (например, получить i в вашем примере), вы должны использовать DOMXPath::evaluate(). SimpleXML::xpath() будет возвращать только список узлов (как и DOMXPath::query(). В php есть также xpath_ методы, но они, похоже, являются функциональными версиями других методов и все еще требуют объектов узлов контекста DOM.

Я не уверен, что такое xml в вашем примере выше, но в примере ниже используется DOMXPath. Насколько я знаю, не существует простого способа конвертировать SimpleXML в DOMDocument. Вам просто нужно загрузить XML отдельно.

$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::*)');
0 голосов
/ 27 октября 2011

Используйте одно выражение XPath, поэтому вам не нужно повторять результат :

elementWithSomeName[@attribute = 'someNeededValue']

или (в случае "атрибута" - это имя элемента):

elementWithSomeName[attribute = 'someNeededValue']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...