【问题标题】:Push nested tag value into PHP array将嵌套标签值推送到 PHP 数组中
【发布时间】:2014-07-25 03:08:15
【问题描述】:

如何使用 PHP DOM 将 sample_id 值连同 firstsamples 一起推送到数组中?

我尝试添加另一个 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);

【问题讨论】:

  • 首先,您的查询看起来不对。

标签: php xml dom xpath


【解决方案1】:

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"

【讨论】:

  • 是否也可以循环遍历子标签sample_id
  • 是的,如果您删除 string() 类型转换。 $xpath-&gt;evaluate('samples/sample_id', $node) 将返回一个节点列表。您可以使用 foreach 对其进行迭代。
【解决方案2】:

您可以使用此 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-&gt;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 选择器。

【讨论】:

  • 如何将附加值first second samples 添加到查询中?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多