将嵌套标记值推送到PHP数组中

时间:2014-07-25 03:08:15

标签: php xml dom xpath

如何使用PHP DOM以及sample_idfirstsamples值推送到数组中?

我尝试添加另一个foreach循环,但我收到了各种通知,例如

Trying to get property of non-object

XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<maintable>
  <group>
    <first>text1</first>
    <second>text2</second>
    <samples a="link" b="link">
      <sample_id>000555</sample_id>
    </samples>
  </group>
  <group>
    <first>text3</first>
    <second>text4</second>
    <samples a="link" b="link">
      <sample_id>111000</sample_id>
    </samples>
  </group>  
</maintable> 

PHP

<?php
$text = file_get_contents($file);
$content = iconv('UTF-8', 'UTF-8//IGNORE', $text);

$xml = new DOMDocument('1.0', 'ISO-8859-1');
$xml->loadXML($content);
$xpath = new DOMXPath( $xml );


$query = '/maintable/group[first="text3"]';                 
$nodes = $xpath->query( $query );


$var = array();
foreach( $nodes as $k => $node )
{
    foreach( $node->childNodes as $cnode )
    {
        if ($cnode->nodeName == 'first')
        {
                $var[$k]["first"] = (string)$cnode->textContent;
        }

        if ($cnode->nodeName == 'samples')
        {
                $var[$k]["samp_url"] = (string)$cnode->getAttribute("a");

        }

        if ($cnode->nextSibling->nodeName == 'sample_id')
        {
                $var[$k]["sample_id"] = (string)$cnode->nextSibling->textContent;

        }
    }   
}
//print_r($cnode->childNodes);
?>

尝试循环通过nodeList

$var = array();

$nodes = $xpath->evaluate('/maintable/group[first="text3"]');
foreach ($nodes as $node) 
{
   foreach( $node->childNodes as $cnode )
   {
       if (is_array($cnode))
       {
           foreach( $cnode->childNodes as $cn )
           {
               $var[]["sample_id"] = (string)$cn->textContent;
           }
       }
   }   
}

var_dump($var);

2 个答案:

答案 0 :(得分:2)

DOMXpath::query()只能返回节点列表,DOMXpath::evaluate()也可以返回标量。 query()/evaluate()的第二个参数是上下文节点。如果提供,则Xpath表达式将相对于它。

因此,您可以先选择节点,迭代列表并再次使用evaluate()来获取值:

$xml = new DOMDocument();
$xml->loadXML($content);
$xpath = new DOMXPath($xml);

$results = [];

$nodes = $xpath->evaluate('/maintable/group[first="text3"]');
foreach ($nodes as $node) {
  $results[] = [
    'first' => $xpath->evaluate('string(first)', $node),
    'sample_url' => $xpath->evaluate('string(samples/@a)', $node),
    'sample_id' => $xpath->evaluate('string(samples/sample_id)', $node)
  ];
}

var_dump($results);

输出:https://eval.in/171656

array(1) {
  [0]=>
  array(3) {
    ["first"]=>
    string(5) "text3"
    ["sample_url"]=>
    string(4) "link"
    ["sample_id"]=>
    string(6) "111000"
  }
}

仅从文档中获取样本ID也是有效的:

var_dump(
  $xpath->evaluate('string(/maintable/group[first="text3"]/samples/sample_id)')
);

输出:

string(6) "111000"

答案 1 :(得分:1)

您可以使用此XPath查询来选择正确的元素:

/maintable/group/first[text()="text3"]/../samples/sample_id

说明:

/maintable                # from the top of the document, select the maintable element
/group                    # select group element, child of maintable
/first[text()="text3"]    # select 'first' element, child of group with text = 'text3'
/..                       # move up to the parent of the 'first' element
/samples                  # find samples element, child of this parent
/sample_id                # find sample_id element, child of this parent

然后,您可以使用$node->nodeValue来推送文本值(示例ID)。例如:

$query = '/maintable/group/first[text()="text3"]/../samples/sample_id';                 
$nodes = $xpath->query($query);

$var = array();
foreach($nodes as $k => $node) {
    $var[] = $node->nodeValue;
}

print_r($var);

输出:

Array
(
    [0] => 111000
)

Here's a good read了解如何使用XPath选择器。