2009-02-27 34 views
45

Tôi có điều này như xml:Parse XML với Namespace sử dụng SimpleXML

<root xmlns:event="http://www.webex.com/schemas/2002/06/service/event"> 
    <event:event> 
     <event:sessionKey></event:sessionKey> 
     <event:sessionName>Learn QB in Minutes</event:sessionName> 
     <event:sessionType>9</event:sessionType> 
     <event:hostWebExID></event:hostWebExID> 
     <event:startDate>02/12/2009</event:startDate> 
     <event:endDate>02/12/2009</event:endDate> 
     <event:timeZoneID>11</event:timeZoneID> 
     <event:duration>30</event:duration> 
     <event:description></event:description> 
     <event:status>NOT_INPROGRESS</event:status> 
     <event:panelists></event:panelists> 
     <event:listStatus>PUBLIC</event:listStatus> 
    </event:event> 
    ... 
</root> 

Làm thế nào tôi có thể lặp qua tất cả các sự kiện: các nút sự kiện và hiển thị, ví dụ, tất cả các sự kiện: SessionKey không?

này không hoạt động:

$xml = new SimpleXMLElement($r); 
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event'); 

foreach($xml->xpath('//e:event') as $event) { 
var_export($event->xpath('//e:sessionKey')); 
} 
+3

này có thể giúp http://www.lornajane.net/posts/2010/Fetching-Namespaced-XML-Elements-With-SimpleXML –

+1

* không hoạt động * là và không bao giờ là một mô tả lỗi chính xác.PHP cung cấp cho bạn lỗi sau: * "Cảnh báo: SimpleXMLElement :: xpath(): Tiền tố không gian tên không xác định" *. Nếu bạn phát triển phần mềm, bạn nên lắng nghe các cảnh báo của PHP. Xem thêm: [Làm thế nào để nhận được thông báo lỗi hữu ích trong PHP?] (Http://stackoverflow.com/q/845021/367456) – hakre

Trả lời

-3

tôi có thể là sai nhưng tôi không nghĩ rằng XML với các biểu tượng thư đại tràng như SOAP có thể được phân tích đúng bằng SimpleXMLElement.

Tôi chắc chắn có cách làm thanh lịch hơn nhưng tôi thường đọc nội dung tệp thành biến bằng cách sử dụng file_get_contents() sau đó thay thế/xóa dấu hai chấm rồi gửi đến SimpleXMLElement.

+0

Trên thực tế, có một số hỗ trợ cho việc đặt tên không gian: http://us.php.net/ manual/en/function.simplexml-element-registerXPathNamespace.php Và tôi biết rằng không gian tên có thể được xóa như sau: $ namespaceFree = preg_replace ('/ ([<< \ /]) ([a-z0- 9] +):/i ',' $ 1 $ 2 ′, $ xml); Tôi chỉ đang tìm kiếm giải pháp tốt hơn. – user38968

+8

Folks. Xin vui lòng. Không sử dụng cụm từ thông dụng hoặc thao tác chuỗi khác khi làm việc với dữ liệu XML. Cơ hội phá vỡ một cái gì đó (ví dụ, "X" của XML (cho "mở rộng")) chỉ đơn giản là quá cao. – scy

24

nó không làm việc mà không registerXPathNamespace và namespace prefix đầy đủ trong các truy vấn xpath:

$xml = new SimpleXMLElement($r); 

foreach($xml->xpath('//event:event') as $event) { 
var_export($event->xpath('event:sessionKey')); 
} 
+1

Có nó hoạt động như một sự quyến rũ! –

+6

Có và không, thực sự tôi coi đây là lỗi. PHP tự động đăng ký các không gian tên của ngữ cảnh hiện tại. Điều này thậm chí ghi đè các không gian tên mà bạn tự đăng ký. Bạn căn cứ nguồn của mình trên các tiền tố được sử dụng trong tài liệu mà bạn tải. Một nguồn bên ngoài bạn không có quyền kiểm soát. Tiền tố được tùy chọn, mơ hồ và có thể thay đổi bất kỳ lúc nào. Không gian tên được xác định, duy nhất và ổn định - tiền tố/bí danh không. – ThW

20

Bạn phải đăng ký tên miền không gian cho mỗi SimpleXMLElement đối tượng bạn sử dụng.

$xml = new SimpleXMLElement($r); 
$xml->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event'); 

foreach($xml->xpath('//e:event') as $event) { 
    $event->registerXPathNamespace('e', 'http://www.webex.com/schemas/2002/06/service/event'); 
    var_export($event->xpath('//e:sessionKey')); 
} 

Không gian tên cũng phải được khai báo ở đâu đó trong tệp xml.

<event:event xmlns:event="http://www.webex.com/schemas/2002/06/service/event"> 
... 

Trục phương pháp được mô tả cũng hoạt động. Bạn có thể bỏ qua registerXPathNamespace nếu bạn biết tệp xml sẽ luôn sử dụng cùng một tiền tố.

3

Sử dụng registerXPathNamespace và sau đó gọi xpath không thực sự hiệu quả đối với tôi. tôi đã phải đi với các giải pháp cung cấp trong bài viết tuyệt vời này: http://blog.preinheimer.com/index.php?/archives/172-SimpleXML,-Namespaces-Hair-loss.html

Vì vậy, trong trường hợp của bạn, điều này:

echo $xml->children('http://www.webex.com/schemas/2002/06/service/event')->sessionName; 

Will đầu ra:

Learn QB in Minutes

6

phương pháp khác là sử dụng SimpleXML cho phân tích cú pháp và DOMDocument để thao tác/truy cập, hoàn toàn bỏ qua các vấn đề về không gian tên:

$xml = new SimpleXMLElement($r); 
$xml = dom_import_simplexml($xml); 
$nodelist= $xml->getElementsByTagName('event'); 
for($i = 0; $i < $nodelist->length; $i++) { 
    $sessions = $nodelist->item($i)->getElementsByTagName('sessionKey'); 
    echo $sessions->item(0)->nodeValue; 
} 
11

đây là giải pháp thay thế phù hợp với tôi.

$xml = simplexml_load_string($r); 
$ns = $xml->getNamespaces(true); 

foreach ($xml->children($ns['event'])->event as $skey) { 
    $sessionKey = $skey->children($ns['event'])->sessionKey; 
    echo $sessionKey; 
} 
+0

Bí quyết đang sử dụng 'children()' với ít nhất tham số đầu tiên của nó. Nếu bạn biết cấu trúc tài liệu trước khi bàn tay, bạn thậm chí có thể gõ tên không gian tên (hoặc URI của nó) theo cách thủ công như là một thay thế cho 'getNamespaces()'. –

2

Đã làm việc rất nhiều với simplexml, đây là cách tôi thực hiện.

Bí quyết kỳ diệu nếu bạn đã có một yếu tố và chỉ muốn nhận được đó là trẻ em namespaced khác nhau, nói cho một cấu trúc như thế này:

<entry> 
<title type="text">My test entry</title> 
<gd:when startTime="2017-02-26T02:00:00Z" endTime="2017-02-26T03:00:00Z"/> 
<gc:notes type="string">A type</gc:notes> 
</entry> 

Là để gửi đúng như tham số thứ hai cho trẻ em Chức năng:

$title = (string) $entry->title; 
    $gd = $entry->children('gd', TRUE); 
    $attrs = $gd->when->attributes(); 
    $startTime = (string) $attrs->startTime; 
    $gc = $entry->children('gc', TRUE); 
    $notes = (string) $gc->notes(); 
+0

Đối với tôi câu trả lời hay nhất. Đơn giản và hiệu quả! – Grzegorz

Các vấn đề liên quan