从多个XML行中提取数据

时间:2015-03-26 15:18:21

标签: php xml attributes xmlnode

我有一个非常奇怪的XML响应,我需要提取它的数据。我需要在"值"中获取数据。属性,但我需要根据他们的"键"属性。

这就是它的样子

       <phone>
       2125556666
       </phone>
       <State>
       ny
       </State>
       <Response>
           <data key="Supported" value="Yes"/>
           <data key="Host" value="Remote"/>
           <data key="WholeProductList">
               <data key="Product" value="a-z44"/>
               <data key="Product" value="c-k99"/>
               <data key="Product" value="e-b089"/>
               <data key="Product" value="z-p00"/>
               <data key="Product" value="r-333"/>
               <data key="Product" value="t-RS232"/>
               <data key="Product" value="4-lve"/>
               <data key="Product" value="Shutdown"/>
           </data>
       </Response>

在PHP中我当前有

$xmltmp = new DomDocument;
$xmltmp->loadXml($response);
$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;
echo $phone;
echo $state;

目前输出电话号码和状态。它工作正常。

现在我需要知道&#34;支持&#34; key的值是Yes或No,如果是,我需要获得所有&#34; Products&#34;。我有点卡住了,因为我很难做出foreach声明,然后检查&#34;键&#34;属性值。

谢谢!

2 个答案:

答案 0 :(得分:3)

您的XML无效。 XML文档始终需要单个文档元素节点。

示例:

<root> 
  <phone>2125556666</phone>
  <State>ny</State>
    <Response>
      <data key="Supported" value="Yes"/>
      ...
    </data>
  </Response>
</root>

从DOM获取数据的最简单方法是XPath。在PHP中由DOMXPath类和ext/dom的一部分提供。 DOMXPath::evaluate()允许您从DOM文档中获取节点列表或标量值。

$dom = new DOMDocument;
$dom->loadXml($xml);
$xpath = new DOMXPath($dom);

$phone = $xpath->evaluate('string(/*/phone)');
$state = $xpath->evaluate('string(/*/State)');
var_dump($phone, $state);

输出:

string(10) "2125556666"
string(2) "ny"

/*/phone这样的表达式选择文档元素中的所有phone元素子节点。 string(/*/phone)将第一个找到的节点强制转换为字符串并返回该字符串。如果没有找到节点,它将返回一个空字符串。

支持状态的XPath表达式稍微复杂一些。节点的条件在[]中提供。可以直接在XPath中比较结果。返回值将是一个布尔值。

$supported = $xpath->evaluate('/*/Response/data[@key="Supported"]/@value = "Yes"');
var_dump($supported);

输出:

bool(true)

如果表达式返回节点列表,您可以使用foreach()迭代它。

$nodes = $xpath->evaluate(
  '/*/Response/data[@key="WholeProductList"]/data[@key="Product"]/@value'
);
$products = [];
foreach ($nodes as $attributeNode) {
  $products[] = $attributeNode->value;
}
var_dump($products);

输出:

array(8) {
  [0]=>
  string(5) "a-z44"
  [1]=>
  string(5) "c-k99"
  [2]=>
  string(6) "e-b089"
  [3]=>
  string(5) "z-p00"
  [4]=>
  string(5) "r-333"
  [5]=>
  string(7) "t-RS232"
  [6]=>
  string(5) "4-lve"
  [7]=>
  string(8) "Shutdown"
}

答案 1 :(得分:1)

这不会“按原样”工作,因为我不知道XML文档的实际结构是什么,但简而言之,您将XML节点映射到XPath,如//root/node/child_node/@attribute,依此类推。

它还应该有一些健全(非空)类型检查。

$xmltmp = new DomDocument;
$xmltmp->loadXml($response);
$xQuery = new DOMXPath($xmltmp);

//not sure what your root node is so the query path is probably wrong
$supported = $xQuery->query('/Response/data[@key="Supported"]/@value')->value;

您也可以替换:

$phone = $xmlresponse->getElementsByTagName('phone')->item(0)->nodeValue;
$state = $xmlresponse->getElementsByTagName('state')->item(0)->nodeValue;

有类似的东西(再次 - 没有XML文档的完整结构,路径本身可能不太正确):

$phone = $xQuery->query('/phone')->item(0)->nodeValue;
$state = $xQuery->query('/State')->item(0)->nodeValue;