Выберите несколько, но не все дочерние узлы - PullRequest
2 голосов
/ 20 октября 2010

У меня есть следующая структура XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<articles>
  <article id="1">
    <title>Article title 001</title>
    <short>Short text</short>
    <long>Long text</long>
  </article>
  <article id="2">
    <title>Article title 002</title>
    <short>Short text</short>
    <long>Long text</long>
  </article>
</articles>

Я хочу выбрать только <title> и <short>.

В настоящее время используется для отображения всего:

 $queryResult = $xpathvar->query('//articles/article'); // works fine grabs all articles
 foreach($queryResult as $result){
   echo $result->textContent;
 }

Ожидаемый результат будет:

Название статьи 001

Краткий текст

Любая помощь будет принята с благодарностью.

Рабочий раствор!

if ($artId == "") {
    $queryResult = $xpathvar->query('//articles/article/*'); // grab all children
    foreach($queryResult as $result){
      if($result->nodeName === 'title' || $result->nodeName === 'short') {
          echo $result->textContent;
      }
    }
}else{
    $queryResult = $xpathvar->query(sprintf('//articles/article[@id="%s"]/*', $artId)); // Show requested article
    foreach($queryResult as $result){
      if($result->nodeName === 'title' || $result->nodeName === 'long') {
          echo $result->textContent;
      }
    }
}

Ответы [ 2 ]

3 голосов
/ 20 октября 2010

Вы можете использовать

/articles/article/*[name()="title" or name()="short"]

, который будет возвращать только дочерние элементы любых "article / article" с именем элемента "title" или "short".


В качестве альтернативы, измените XPath на /articles/article/*, чтобы получить все дочерние узлы статьи, и при итерации $results проверьте, является ли DOMNode::nodeName "заголовком" или "коротким", например,

$queryResult = $xpathvar->query('/articles/article/*'); // grab all children
foreach($queryResult as $result){
  if($result->nodeName === 'title' || $result->nodeName === 'short') {
      echo $result->textContent;
  }
}

Если вы не хотите менять XPath, вам нужно повторить childNodes статьи, например,

$queryResult = $xpathvar->query('/articles/article');
foreach($queryResult as $result) {
  foreach($result->childNodes as $child) {       
  if($child->nodeName === 'title' || $child->nodeName === 'short') {
      echo $child->textContent;
  }
}
1 голос
/ 20 октября 2010

Используйте :

/*/*/*[self::title or self::short]

или если title и short детей определенного article с известным @id (скажем '2') должны бытьотображается:

/*/article[@id='2']/*[self::title or self::short]

Всегда старайтесь избегать использования сокращения // , когда это возможно (когда известна структура XML-документа).

Использование // очень часто приводит к крайне неэффективной оценке, потому что // вызывает поиск всего (под) дерева, имеющего корни в текущем узле.

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