XPath一次选择多个元素?

时间:2016-09-29 22:53:03

标签: php xml xpath

我目前这样做是为了构建一个名为$tables的数组,但想知道是否有更简单的方法可以做到这一点?

$tables = array();
$abbr = $states_xml->xpath('//StateAbbr');
$names = $states_xml->xpath('//StateName');

// State Abbreviations...
while(list($key,$table) = each($abbr)) {
    $tables[$key]['Abbr'] = (string) trim($table);
}

// State Names...
while(list($key,$name) = each($names)) {
    $tables[$key]['Name'] = (string) trim($name);
}

是否可以在1中调用StateAbbrStateName个元素,并以与$tables相同的格式输出数组?

因此,tables数组看起来像这样:

array(57) {
  [0]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AL"
    ["Name"]=>
    string(7) "Alabama"
  }
  [1]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AK"
    ["Name"]=>
    string(6) "Alaska"
  }
  [2]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AS"
    ["Name"]=>
    string(14) "American Samoa"
  }
... and so on...

基本上,$states_xml看起来像这样:

<diffgr:diffgram
    xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
    xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <NewDataSet
        xmlns="">
        <Table diffgr:id="Table1" msdata:rowOrder="0">
            <StateAbbr>AL </StateAbbr>
            <StateName>Alabama</StateName>
        </Table>
        <Table diffgr:id="Table2" msdata:rowOrder="1">
            <StateAbbr>AK </StateAbbr>
            <StateName>Alaska</StateName>
        </Table>
        <Table diffgr:id="Table3" msdata:rowOrder="2">
            <StateAbbr>AS </StateAbbr>
            <StateName>American Samoa</StateName>
        </Table>
        <Table diffgr:id="Table4" msdata:rowOrder="3">
            <StateAbbr>AP </StateAbbr>
            <StateName>AP</StateName>
        </Table>
        ...
    </NewDataSet>
</diffgr:diffgram>

我正在使用$states_xml = simplexml_load_string(THE STRING ABOVE);将xml加载到$states_xml

无论如何要从这里的所有StateAbbr元素中获取所有StateNameTable以便在一个数组中输出?对我来说似乎可能,但不知道如何处理这个问题,而不是我目前正在做的事情。

3 个答案:

答案 0 :(得分:1)

您应该迭代其父元素节点。表达式相对于SimpleXMLElement表示的节点,但在您的情况下不需要:

$diffgram = new SimpleXMLElement($xml);

$result = [];
foreach($diffgram->xpath('.//Table') as $table) {
  $result[] = [
    'Abbr' => trim($table->StateAbbr),
    'Name' => trim($table->StateName)
  ];
}

var_dump($result);

输出:

array(4) {
  [0]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AL"
    ["Name"]=>
    string(7) "Alabama"
  }
  [1]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AK"
    ["Name"]=>
    string(6) "Alaska"
  }
  [2]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AS"
    ["Name"]=>
    string(14) "American Samoa"
  }
  [3]=>
  array(2) {
    ["Abbr"]=>
    string(2) "AP"
    ["Name"]=>
    string(2) "AP"
  }
}

在DOM中它看起来几乎相同,但在这里你需要Xpath表达式来获取细节。

$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);

$result = [];
foreach($xpath->evaluate('.//Table') as $table) {
  $result[] = [
    'Abbr' => $xpath->evaluate('normalize-space(StateAbbr)', $table),
    'Name' => $xpath->evaluate('normalize-space(StateName)', $table)  
  ];
}

var_dump($result);

答案 1 :(得分:0)

请使用array_merge_recursive尝试此操作:

$abbr = $states_xml->xpath('//StateAbbr');
$names = $states_xml->xpath('//StateName');
$tables = array_merge_recursive($abbr, $names);

显示:

print_r($tables);

答案 2 :(得分:0)

是的,这个单一的XPath,

//*[self::StateAbbr or self::StateName]

将返回XML文档中的所有StateAbbrStateName元素。