2015-09-03 73 views
0

這是通過API返回正確分析:PHP的SimpleXMLElement不與命名空間

<?xml version='1.0' encoding='utf-8'?> 
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="https://exmple.com/odata/"> 
    <id>https://example.com/odata/PicklistOption(989L)</id> 
    <title type="text" /> 
    <updated>2015-09-03T11:56:51Z</updated> 
    <author> 
     <name /> 
    </author> 
    <link rel="edit" title="PicklistOption" href="PicklistOption(989L)" /> 
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/childPicklistOptions" type="application/atom+xml;type=feed" title="childPicklistOptions" href="PicklistOption(989L)/childPicklistOptions" /> 
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/parentPicklistOption" type="application/atom+xml;type=entry" title="parentPicklistOption" href="PicklistOption(989L)/parentPicklistOption" /> 
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/picklistLabels" type="application/atom+xml;type=feed" title="picklistLabels" href="PicklistOption(989L)/picklistLabels" /> 
    <link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/picklist" type="application/atom+xml;type=entry" title="picklist" href="PicklistOption(989L)/picklist" /> 
    <category term="SFOData.PicklistOption" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
    <content type="application/xml"> 
     <m:properties> 
      <d:id m:type="Edm.Int64">989</d:id> 
      <d:status>ACTIVE</d:status> 
      <d:sortOrder m:type="Edm.Int32">229</d:sortOrder> 
      <d:minValue m:type="Edm.Double">-1</d:minValue> 
      <d:externalCode>PL</d:externalCode> 
      <d:optionValue m:type="Edm.Double">-1</d:optionValue> 
      <d:maxValue m:type="Edm.Double">-1</d:maxValue> 
     </m:properties> 
    </content> 
</entry> 

現在試圖讓<d:id>

$xml = new SimpleXMLElement($xmlstr); 
$namespaces = $xml->getNameSpaces(true); 
$xml->registerXPathNamespace('m', $namespaces['m']); 
$xml->registerXPathNamespace('d', $namespaces['d']); 

$id = $xml->xpath('/entry/content/m:properties/d:id'); 
var_dump($id); 

,但我得到array(0)

回答

1

不要從文檔中獲取名稱空間。在你的應用程序中定義它們。命名空間是xmlns/xmlns:*屬性的值。 xmlns屬性是默認的名稱空間。所以標籤entry實際上是{http://www.w3.org/2005/Atom}:entry

命名空間必須是唯一的。爲了避免衝突,大多數人使用URL。 (其他人不太可能使用你的域來定義它們的名字空間。)這個名字空間的缺點是大字符串有特殊字符。這是通過使用名稱空間前綴作爲別名來解決的。

Xpath沒有默認名稱空間。您需要爲每個您喜歡的名稱空間註冊一個前綴。 Xpath引擎會將前綴解析爲實際名稱空間,並將其與節點的已解析名稱空間進行比較。

$xml = new SimpleXMLElement($xmlstr); 
$namespaces = [ 
    'a' => 'http://www.w3.org/2005/Atom', 
    'm' => 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata', 
    'd' => 'http://schemas.microsoft.com/ado/2007/08/dataservices', 
    'o' => 'https://exmple.com/odata/' 
]; 
foreach ($namespaces as $prefix => $namespace) { 
    $xml->registerXPathNamespace($prefix, $namespace); 
} 

$id = $xml->xpath('/a:entry/a:content/m:properties/d:id'); 
var_dump($id); 

輸出:

array(1) { 
    [0]=> 
    object(SimpleXMLElement)#2 (0) { 
    } 
} 

你將不得不重新註冊每個SimpleXMLElement獲得XPath名稱空間。

這在DOM中更方便。 DOMXpath::evaluate()執行Xpath表達式並根據表達式返回節點列表或標量。

$document = new DOMDocument($xmlstr); 
$document->loadXml($xmlstr); 
$xpath = new DOMXpath($document); 
$namespaces = [ 
    'a' => 'http://www.w3.org/2005/Atom', 
    'm' => 'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata', 
    'd' => 'http://schemas.microsoft.com/ado/2007/08/dataservices', 
    'o' => 'https://exmple.com/odata/' 
]; 
foreach ($namespaces as $prefix => $namespace) { 
    $xpath->registerNamespace($prefix, $namespace); 
} 

$id = $xpath->evaluate('string(/a:entry/a:content/m:properties/d:id)'); 
var_dump($id); 

輸出:

string(3) "989" 
+0

輝煌!謝謝! –