XML 採用命名空間避免元素名稱衝突。SimpleXML 預設只能存取無命名空間或預設命名空間的元素,需顯式指定命名空間 URI 才能存取 gd:phoneNumber、gContact:groupMembershipInfo 等前綴元素。
<feed xmlns="https://www.w3.org/2005/Atom"
xmlns:gd="https://schemas.google.com/g/2005"
xmlns:gContact="https://schemas.google.com/contact/2008">
<entry>
<id>https://www.google.com/m8/feeds/contacts/liz%40gmail.com/base/c9012de</id>
<title>Fitzwilliam Darcy</title>
<gd:name>
<gd:fullName>Fitzwilliam Darcy</gd:fullName>
</gd:name>
<gd:phoneNumber rel="https://schemas.google.com/g/2005#home" primary="true">456</gd:phoneNumber>
<gContact:groupMembershipInfo href="https://www.google.com/m8/feeds/groups/liz%40gmail.com/base/270f" />
</entry>
</feed>
<?php
$xmlString = file_get_contents('contacts.xml');
$feed = new SimpleXMLElement($xmlString);
// 註冊命名空間前綴(方便 XPath 使用)
$feed->registerXPathNamespace('gd', 'https://schemas.google.com/g/2005');
$feed->registerXPathNamespace('gc', 'https://schemas.google.com/contact/2008');
foreach ($feed->entry as $entry) {
// 1. 取得預設命名空間元素
echo "ID: " . $entry->id . "\n";
echo "Title: " . $entry->title . "\n";
// 2. 進入 gd 命名空間
$gd = $entry->children('https://schemas.google.com/g/2005');
echo "Phone: " . $gd->phoneNumber . "\n"; // 456
echo "Phone Rel: " . $gd->phoneNumber['rel'] . "\n"; // 屬性存取
// 3. 進入 gContact 命名空間
$gc = $entry->children('https://schemas.google.com/contact/2008');
echo "Group: " . $gc->groupMembershipInfo['href'] . "\n";
// 4. 使用 XPath 直接查詢(更彈性)
$phones = $entry->xpath('gd:phoneNumber');
foreach ($phones as $phone) {
echo "XPath Phone: $phone\n";
}
}
?>
<?php
$feed = new SimpleXMLElement($xmlString);
// 取得元素及其子孫使用的所有命名空間
$namespaces = $feed->getNamespaces(true); // true = 遞迴取得
foreach ($feed->entry as $entry) {
$ns = $entry->getNamespaces(true);
// $ns = ['gd' => 'https://schemas.google.com/g/2005', 'gContact' => '...']
// 使用前綴鍵名進入
$gd = $entry->children($ns['gd']);
echo $gd->phoneNumber;
}
?>
若 XML 缺少命名空間宣告(如 `
<?php
// 1. 抑制警告(不推薦生產環境)
$xml = @new SimpleXMLElement($malformedXml);
// 2. 預處理:補全 xmlns 或移除前綴(推薦)
$cleanXml = preg_replace('/\b(\w+):(\w+)/', '$2', $malformedXml); // 移除所有前綴
$xml = new SimpleXMLElement($cleanXml);
// 3. 或使用 DOMDocument 載入後再轉 SimpleXML(最穩健)
$dom = new DOMDocument();
$dom->loadXML($malformedXml, LIBXML_NOERROR | LIBXML_NOWARNING);
$xml = simplexml_import_dom($dom);
?>
| 特性 | SimpleXML | DOMDocument |
|---|---|---|
| API 風格 | 屬性/陣列存取,直覺 | 標準 DOM API,冗長 |
| 命名空間支援 | 需手動指定 URI | 完整支援,getElementsByTagNameNS |
| 記憶體效率 | 載入整份文件 | 載入整份文件 |
| 寫入/修改 | 有限(可修改值、屬性) | 完整建立/修改/刪除節點 |
| XPath | 支援 xpath() | 支援 DOMXPath |
| 大檔案串流 | 不支援 | 不支援(需 XMLReader) |
掌握 children($namespaceURI)、getNamespaces(true)、registerXPathNamespace() 三大招式,即可從容應對 Google、Amazon、微信支付等主流 API 的複雜命名空間 XML。遇到不標準 XML,優先預處理或改用 DOMDocument,避免依賴錯誤抑制。