2015-09-22 30 views
2

欧洲中央银行提供依赖欧元的XML document for currency exchange rates如何使用phpstorm评估特定namesapce的xpath?

<?xml version="1.0" encoding="UTF-8"?> 
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"> 
    <gesmes:subject>Reference rates</gesmes:subject> 
    <gesmes:Sender> 
     <gesmes:name>European Central Bank</gesmes:name> 
    </gesmes:Sender> 
    <Cube> 
     <Cube time='2015-09-17'> 
      <Cube currency='USD' rate='1.1312'/> 
      <Cube currency='JPY' rate='136.76'/> 
      <Cube currency='BGN' rate='1.9558'/> 
      ... 
     </Cube> 
    </Cube> 
</gesmes:Envelope> 

我已将此XML文件存储为货币汇率提供商的测试用例,因为我想为其编写解析器。

我想使用phpstorm的Evaluate XPath...功能。

但它似乎没有认识到命名空间;所以它没有找到任何匹配的//Cube

Evaluate XPath window

我也尝试过使用Show unique XPath,对我来说显示

/gesmes:Envelope/e:Cube/e:Cube/e:Cube/@rate

然而,使用这种在没有repsonse评估产量。

我想我有它malconfigured(因为我试图编辑上下文,但我不知道我在做什么)。

Edit Xpath Context

如何设定正确的命名空间?

回答

2

您使用前缀e作为Xpath表达式中的名称空间http://www.ecb.int/vocabulary/2002-08-01/eurofxref,但为其配置了前缀c

您不需要在PHP中为它编写解析器。只需使用DOM + Xpath。

$document = new DOMDocument(); 
$document->loadXml($xml); 
$xpath = new DOMXpath($document); 
$xpath->registerNamespace('gesmes', 'http://www.gesmes.org/xml/2002-08-01'); 
$xpath->registerNamespace('e', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref'); 

$time = $xpath->evaluate('string(/gesmes:Envelope/e:Cube/e:Cube/@time)'); 

$rates = []; 
foreach ($xpath->evaluate('/gesmes:Envelope/e:Cube/e:Cube/e:Cube') as $cube) { 
    $rates[$cube->getAttribute('currency')] = $cube->getAttribute('rate'); 
} 

var_dump($time, $rates); 

输出:

string(10) "2015-09-22" 
array(31) { 
    ["USD"]=> 
    string(6) "1.1155" 
    ["JPY"]=> 
    string(6) "133.75" 
    ["BGN"]=> 
    string(6) "1.9558" 
    ["CZK"]=> 
    string(6) "27.057" 
    ["DKK"]=> ... 
0

您需要告诉XPath哪些名称空间绑定了哪些前缀,或者为您的表达式中的前缀名称设置默认名称空间。并非所有主机语言都支持设置。

在PHPStorm中,您可以点击按钮编辑上下文...see documentation

如果由于某种原因,你可以不设置此得当,你可以使用一个名称的本地名称使用查询,然后将查询变为:

/*[local-name() = 'Envelope'] 
    /*[local-name() = 'Cube'] 
    /*[local-name() = 'Cube'] 
    /*[local-name() = 'Cube']/@rate 

不理想,但它会工作。 ⑴任何XML名称都包含本地部分,如果没有冒号,前缀部分是冒号前的部分,名称空间部分是冒号或全名后的部分该前缀绑定到的名称空间。 XML名称由其local-name及其名称空间确定性地定义,前缀无关紧要。