【问题标题】:XPath to select multiple elements at once?XPath一次选择多个元素?
【发布时间】:2016-09-29 22:53:02
【问题描述】:

我目前正在这样做以构建一个名为 $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);
}

是否可以一次性调用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

无论如何要从这里的所有Table 元素中获取所有StateAbbrStateName 以一次性输出到数组中??对我来说似乎是可能的,但除了我目前正在做的方式之外,我不确定如何解决这个问题。

【问题讨论】:

    标签: php xml xpath


    【解决方案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);
    

    【讨论】:

      【解决方案2】:

      请使用array_merge_recursive 试试这个:

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

      显示:

      print_r($tables);
      

      【讨论】:

        【解决方案3】:

        是的,这个单一的 XPath,

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

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

        【讨论】:

        • 不,不幸的是,这不起作用。我用 xml 字符串的输出更新了问题。
        • 嗯,它确实完成了它的设计目的:使用单个 XPath 选择所有 StateAbbrStateName 元素。如果您确实想保留StateAbbrStateName 元素之间的关联,那么为什么不选择所有表呢?例如://Table
        • 因为//Table 返回的信息太多,无法轻松解析。无论如何,我决定放弃xpath 方法,只需执行$states = json_decode(json_encode($states_xml), true);,之后就非常简单了,只需要调用$states['NewDataSet']['Table'],它就可以满足我的需求。感谢您的帮助。 :)
        • 当然可以。很高兴您找到了满足您需求的东西。
        猜你喜欢
        • 1970-01-01
        • 2015-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-10
        • 1970-01-01
        • 2022-10-14
        相关资源
        最近更新 更多