Hiển thị các sự kiện Google Calendar trên trang Web PHP của bạn với XPath

XPath và SimpleXML cung cấp sự cân bằng hợp lý giữa khả năng đọc và sự dài dòng trong các API phân tích cú pháp-XML

Google Calendar (Lịch của Google) và các ứng dụng lịch trực tuyến khác cung cấp các hệ thống tập trung đơn giản ở nơi các cộng đồng trực tuyến có thể duy trì các lịch sự kiện và các thành viên cộng đồng có thể nhận được thông tin về các sự kiện sắp tới. Tuy nhiên, nhiều tổ chức thích hiển thị các lịch sự kiện trên các cổng thông tin, các diễn đàn, hoặc các blog cộng đồng của họ. Họ thường xuyên sao chép thông tin lịch sự kiện từ các ứng dụng tạo lịch trực tuyến lên trang Web của họ, nên đã làm giảm hiệu quả của việc quản lý tập trung trực tuyến các sự kiện. Google Calendar cung cấp một giao diện lập trình ứng dụng (API) tích hợp nhằm cung cấp một giải pháp tốt cho vấn đề này. Hãy tìm hiểu cách sử dụng XPath để trích xuất và hiển thị dữ liệu Google Calendar trên trang Web PHP của bạn.

PJ Cabrera, Kỹ sư phần mềm, 自由职业者

P.J. CabreraPJ Cabrera là một nhà phát triển chuyên về phát triển các hệ thống quản lý nội dung và thương mại điện tử Ruby on Rails. Ông quan tâm về Ruby on Rails và các ngôn ngữ kịch bản lệnh và các khung công tác mã nguồn mở, các thực hành phát triển nhanh, các mạng lưới, các đám mây điện toán, các công nghệ phân tích cú pháp và xử lý XML, các định dạng cực nhỏ cho nhiều nội dung Web ngữ nghĩa hơn, và nghiên cứu sử dụng sáng tạo về lọc Bayesian và xử lý ký hiệu để cải thiện lấy ra thông tin, trả lời câu hỏi, phân loại văn bản, và trích xuất. Đọc Weblog của ông tại pjtrix.com/blawg/.



30 11 2011

Trong lúc hành nghề tự do như một nhà phát triển Web một vài năm trước đây, tôi đã phát triển một cổng thông tin Web có trang bị-PHP cho một cộng đồng những người sở hữu và những người hâm mộ một mẫu ô tô cụ thể (thường được gọi là câu lạc bộ xe hơi đang rất phổ biến ở nơi tôi sống). Một vài năm trước khi liên hệ với tôi, một số các nhà lãnh đạo câu lạc bộ xe hơi đã học được các kỹ năng Web cơ bản và đã tạo ra một trang Web riêng của họ. Khi đã phát triển, trang Web này đã tích lũy được một số lượng lớn các trang, một số trang trở nên nhàm chán, ở đó đăng lên thông tin lịch sự kiện riêng biệt. Do mục đích chính của trang là thông báo cho công chúng và các thành viên cộng đồng về các hoạt động, nên người ta đã đăng bừa bãi thông tin lịch sự kiện lên các trang này.

Theo thời gian, những ảnh chụp màn hình tạp nham này về lịch sự kiện của cộng đồng đã phát triển không đồng bộ. Một số trang vẫn có các thanh bên thông báo các sự kiện đã lỗi thời. Ngay cả với việc quản lý đúng cách và thiết kế Web hiệu quả, việc duy trì các bản sao dữ liệu lịch sự kiện riêng biệt trên các trang riêng biệt là một quá trình tiêu tốn nhiều thời gian và dễ bị lỗi. Thay vì trang Web của câu lạc bộ xe làm việc cho họ, họ lại thấy mình làm việc chăm chỉ cho trang Web của mình. Họ liên lạc với tôi với hy vọng rằng tôi có thể chỉ họ một cách tốt hơn.

Họ đã cần một trang Web có các diễn đàn ở đó các thành viên câu lạc bộ có thể thảo luận về những chiếc xe yêu thích của mình và một trang tin tức tập trung có các bài viết và các thông báo về sự kiện mới nhất. Trên trang tin tức này, họ có thể thông báo cho thành viên đang tăng dần của mình về các sự kiện, ví dụ như các cuộc gặp mặt, các chuyến đi caravan tới các vùng đất và xung quanh các vùng nông thôn, và các cuộc họp thành viên chung ở đó họ đã thảo luận về lệ phí hội viên và xem xét về dự thảo ngân sách. Quan trọng hơn, họ không muốn phải duy trì nhiều hoặc càng nhiều bản sao lịch sự kiện ở bất cứ đâu. Họ muốn đưa lịch sự kiện về một chỗ và có thể truy cập thông tin đó từ bất cứ nơi nào khác trên trang Web.

Google Calendar và API dữ liệu của Google

Các ứng dụng tạo lịch trực tuyến như Google Calendar cung cấp một giải pháp. Nhờ tập trung hiển thị và quản lý các sự kiện, những người dùng Google Calendar có thể chia sẻ và duy trì dữ liệu sự kiện tại một trang Web, loại bỏ một trong nhiều nguồn sai sót khỏi quá trình tổ chức sự kiện. Các thành viên cộng đồng có thể truy cập lịch trực tuyến để bám sát các sự kiện sắp tới và các hoạt động mà không bị nhầm lẫn bởi thông tin sự kiện quá hạn trên các trang Web riêng biệt. Có vẻ như các ứng dụng lịch trực tuyến là giải pháp lý tưởng.

Trong khi phát triển trang Web của câu lạc bộ bằng hệ thống quản lý nội dung Drupal (xem phần Tài nguyên), tôi đã đề nghị các nhà lãnh đạo của câu lạc bộ sử dụng Google Calendar để duy trì lịch sự kiện. Lúc đầu, họ đã hiểu được ý tưởng này, và họ đã báo cáo năng suất rất cao vì đã dễ dàng sử dụng đầu vào quản trị của Drupal để cập nhật các thanh bên sự kiện mà tôi đã tạo ra cho họ. Nhưng theo thời gian, sự thành công của câu lạc bộ có nghĩa là có nhiều sự kiện hơn để thông báo, và việc chỉnh sửa các thanh bên sự kiện đã chuyển từ vui vẻ và dễ dàng thành một công việc vụn vặt khó chịu.

API dữ liệu của Google và việc truy cập của nó tới dữ liệu sự kiện Google Calendar đã đưa ra một cách thực hiện để thoát ra khỏi tình trạng khó xử này. API dữ liệu của Google cung cấp một công cụ của Giao thức xuất bản Atom (APP), một API dịch vụ Web để đọc và cập nhật các kiểu tài liệu và thông tin khác nhau. Ngoài ra còn có các API tích hợp của bên thứ ba cho ngôn ngữ lập trình Microsoft® .NET, Java™, Python và PHP chứa đựng nhiều chức năng của API dữ liệu Google trong một tập các lớp trình bao hướng đối tượng.

Sau một số nghiên cứu, tôi đã có thể mở rộng trang Web Drupal của câu lạc bộ xe hơi với một thanh bên sự kiện luôn cập nhật dữ liệu lịch sự kiện mới nhất được lấy từ tài khoản Google Calendar.


Nguồn cung cấp tin của Google Calendar

API dữ liệu Google cung cấp một số các nguồn cung cấp tin Atom có chứa các tài liệu và thông tin với nhiều dịch vụ Web do Google cung cấp. Google Calendar cũng không là ngoại lệ, cung cấp một số nguồn cung cấp tin đang chứa đựng phần lớn dữ liệu của Google Calendar. Có các nguồn cung cấp tin công khai và có xác thực HTTP. Để lấy ra và tương tác với nguồn cung cấp tin có xác thực, máy khách HTTP cần phải cung cấp thông tin xác thực cùng với yêu cầu GET của HTTP. Các nguồn cung cấp tin có xác thực cũng có khả năng cập nhật tài khoản Google Calendar bằng yêu cầu POST của HTTP. Các máy khách HTTP đang sử dụng các nguồn cung cấp tin có xác thực có thể thêm và loại bỏ các sự kiện, đăng ký và huỷ đăng ký khỏi các lịch, và tạo và xóa các lịch khỏi tài khoản Google.

Google Calendar API cung cấp các nguồn cung cấp tin để truy cập vào tất cả các lịch cá nhân mà người dùng đã truy cập vào từ Giao diện người dùng đồ họa (GUI) của Google Calendar. Việc này bao gồm các lịch thuộc sở hữu của người dùng, các lịch thuộc sở hữu của người khác nhưng người dùng đã đăng ký, và các lịch mà người dùng đã nhập khẩu trong trạng thái chỉ-đọc. Các lịch này, mà mỗi cái đều là nguồn cấp tin riêng của mình, đã xác thực các nguồn cung cấp tin sự kiện công khai và riêng tư, ở đó các sự kiện cá nhân trong lịch được liệt kê. Bài viết này tập trung vào các nguồn cung cấp tin sự kiện công khai.

Tạo công khai nguồn cung cấp tin Google Calendar của bạn

Nguồn cung cấp tin sự kiện công khai của một lịch của Google Calendar, trong đó một tài khoản có thể có nhiều, nhận được bằng cách đăng ký vào ứng dụng Google Calendar, cách chọn lịch mà bạn đang quan tâm xử lý, và cách nhấn vào mũi tên đi xuống nhỏ cạnh tên của lịch. Sau khi bạn nhấn vào mũi tên này, một trình đơn hiển thị bên cạnh tên của nguồn cung cấp tin. Chọn Calendar Settings (Các thiết lập Lịch), được khoanh tròn trong Hình 1.

Hình 1. Trình đơn thả xuống Google Calendar cho một lịch được chọn
Trình đơn thả xuống Google Calendar cho một lịch được chọn

Sau đó, ứng dụng Google Calendar chuyển đến một trang ở đó bạn có thể chọn các thiết lập lịch khác nhau, ví dụ như múi giờ cho các sự kiện và tên của lịch. Một tùy chọn quan trọng cho các nguồn cung cấp tin công khai là liệu lịch tự nó có là lịch công khai hay lịch chia sẻ không. Để làm cho lịch của bạn được chia sẻ và có thể lấy ra thông qua nguồn cung cấp tin sự kiện công khai, hãy nhấn chuột vào tùy chọn Change sharing settings (Thay đổi các thiết lập chia sẻ), như trong Hình 2.

Hình 2. Thay đổi khả năng nhìn thấy của một lịch theo được chia sẻ hoặc công khai
Thay đổi khả năng nhìn thấy của một lịch theo được chia sẻ hoặc công khai

Trang sẽ chuyển tới thẻ (tab) Share this calendar (Chia sẻ lịch này), ở đây bạn có thể chọn Share all information on this calendar with everyone (Chia sẻ tất cả thông tin trên lịch này với mọi người). Một loạt các câu hỏi hiện lên sẽ hiển thị, hỏi liệu bạn có thực sự muốn tạo công khai lịch của bạn không. Trả lời Yes (Có), và đừng quên lưu các thiết lập của mình bằng cách nhấn chuột vào Save (Lưu) ở phía dưới cùng của thẻ này. Nhấn vào Back to Calendar (Quay lại Lịch) để tiếp tục bổ sung thêm các sự kiện vào lịch của bạn.

Xem xét một nguồn cung cấp tin của Google Calendar

Với một ví dụ về một nguồn cung cấp tin của Google Calendar, hãy tham khảo tệp full.xml trong ví dụ mã được cung cấp trong phần Tải về. Tôi cũng cung cấp một liên kết đến một nguồn cung cấp tin giả được sử dụng trong các ví dụ mã trong bài viết này (xem phần Tài nguyên).

Các nguồn cung cấp tin sự kiện chứa các phần tử khác nhau để mô tả một sự kiện, ví dụ như tên sự kiện, một đoạn mô tả, và ở đâu và khi nào sẽ diễn ra sự kiện đó. Google Calendar cũng quản lý một danh sách những người được mời đến sự kiện thông qua một danh sách các e-mail để gửi các thông tin chi tiết sự kiện bất cứ khi nào email được cập nhật. Nếu các địa chỉ e-mail này đại diện cho những người dùng Google Calendar, thì họ có thể đáp ứng lời mời thông qua ứng dụng, và sự kiện này cũng duy trì trạng thái tham dự của họ. Việc tích hợp với các thông tin chi tiết tham dự nằm ngoài phạm vi của bài viết này, là chỉ tập trung vào thông tin sự kiện cơ bản, ví dụ như tên sự kiện và khi nào và ở đâu các sự kiện sẽ diễn ra. Liệt kê 1 là một mục sự kiện từ nguồn cung cấp tin mẫu.

Liệt kê 1. Nguồn cung cấp tin sự kiện mẫu của Google Calendar: ID và các dấu thời gian
    <entry>
	    <id>
            http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/public/full/
            s19o15ve3nn209gv5qf6c43ao4
        </id>
        <published>2007-08-12T15:45:40.000Z</published>
        <updated>2007-08-12T15:53:37.000Z</updated>
        ...
        ...

Phần tử id (mã định danh) cung cấp một địa chỉ URI (Uniform Resource Identifier - Trình định danh tài nguyên thống nhất) duy nhất để nhận biết sự kiện này bên trong hệ thống Google Calendar. Phần tử này không chỉ chứa một số duy nhất mà còn nhận biết nguồn cung cấp tin từ đó lấy ra nó. Các phần tử published (đã công bố) và updated (đã cập nhật) sử dụng định dạng dấu thời gian RFC 3339. Phần tử updated cho biết khi nào chỉnh sửa sự kiện lần cuối, hoặc trong trường hợp có một sự kiện mới, khi nào tạo ra nó.

Sau các phần tử id, published, và updated đến các phần tử có thông tin dễ đọc cho mọi người hơn, như trong Liệt kê 2. Có thể hiển thị thông tin này trong một thanh bên hoặc trang các sự kiện.

Liệt kê 2. Mục nguồn cung cấp tin sự kiện mẫu của Google Calendar: tên, tác giả, và trạng thái
        ...
        ...

        <title type="text">Linux Install Fest</title>
        ...
        ...

        <author>
            <name>Open Source San Juan</name>
            <email>foss.sanjuan@gmail.com</email>
        </author>
        ...
        ...

        <gd:eventStatus value="http://schemas.google.com/g/2005#event.confirmed"/>
        ...
        ...

Phần tử title (tên) là một chuỗi đơn giản để nhận ra sự kiện đó. Nó không cần phải là duy nhất. Phần tử author (tác giả) chứa phần tử nameemail. Tác giả của sự kiện là người dùng Google Calendar, những người đã nhập sự kiện vào trong lịch. Với nguồn cung cấp tin có xác thực và các quyền ghi được thiết lập phù hợp, những người dùng Google Calendar khác với người chủ sở hữu của lịch có thể tạo các sự kiện trên lịch của người dùng khác. Bảng 1 mô tả các giá trị có thể với phần tử status (trạng thái).

Bảng 1. Các giá trị có thể với phần tử gd:eventStatus
Giá trịMô tả
http://schemas.google.com/g/2005#event.cancelledXóa bỏ sự kiện này.
http://schemas.google.com/g/2005#event.confirmedXác nhận sự kiện này.
http://schemas.google.com/g/2005#event.tentativeLập lịch biểu thăm dò cho sự kiện này.

Bây giờ đến các phần tử mô tả thời gian và địa điểm ở đó sẽ diễn ra sự kiện này, như trong Liệt kê 3.

Liệt kê 3. Mục nguồn cung cấp tin sự kiện mẫu của Google Calendar: When và where
        ...
        ...

        <gd:when startTime="2007-08-03T16:00:00.000-04:00" 
            endTime="2007-08-03T19:00:00.000-04:00"/>
        <gd:where 
            valueString="Guaynabo Public High School Auditorium, Guaynabo, PR"/>
    </entry>

Phần tử when chứa hai thuộc tính: thời gian bắt đầu và kết thúc của sự kiện, cả hai đều theo định dạng dấu thời gian RFC 3339. Thuộc tính valueString của phần tử where có đủ khả năng tìm kiếm từ ứng dụng Google Calendar và thông qua API. Google Calendar và API dữ liệu Google không hỗ trợ tìm kiếm bằng các phần tử riêng. Thay vào đó, chúng tìm kiếm toàn văn bản trên các phần tử string (chuỗi), ví dụ như title, author, description và thuộc tính valueString của phần tử where. Như bạn sẽ thấy sau này, trường hợp ngoại lệ là API dữ liệu Google hỗ trợ các phạm vi thiết lập các ngày bắt đầu để hạn chế các sự kiện nào được chứa trong các kết quả truy vấn.

Hạn chế các nội dung của nguồn cung cấp tin Google Calendar

Để hỗ trợ phục hồi các tập dữ liệu chính xác, API dữ liệu Google hỗ trợ khái niệm về các tham số truy vấn bằng yêu cầu GET của HTTP. Khi sử dụng các tham số này, máy khách API dữ liệu Google có thể quy định số lượng tối đa các mục để trả về (với tham số max-results), phần tử nào sử dụng để phân loại các mục trong nguồn cung cấp tin (thông qua tham số orderby) và toàn bộ thời gian bắt đầu và thời gian kết thúc trong phạm vi các mục để trả về (thông qua các tham số start-minstart-max ). Hai tham số cuối cùng này nói đến phạm vi ngày của thời gian bắt đầu sự kiện được chứa trong tập kết quả các sự kiện. start-min nói đến ngày bắt đầu trong phạm vi đó và start-max nói đến ngày kết thúc của phạm vi đó. Cả hai đều được biểu thị theo định dạng dấu thời gian RFC 3339.

Cuối cùng, bạn có thể tạo cho các sự kiện định kỳ dễ dàng hơn để phân tích cú pháp bằng cách dùng tham số singleevents trong chuỗi truy vấn. Khi tham số singleevents có một giá trị đúng, các sự kiện định kỳ được quy định trong nguồn cung cấp tin như thể chúng đã là các sự kiện đơn lẻ khác biệt. Ngược lại, các sự kiện định kỳ có một phần tử <gd:recurrence> chứa các quy tắc định kỳ theo định dạng iCal. Định dạng iCal và cách phân tích cú pháp nó nằm ngoài phạm vi của bài viết này.

Địa chỉ URL của nguồn cung cấp tin sự kiện trông giống như trong Liệt kê 4 với tất cả các tham số truy vấn bổ sung. Nó đã được biên tập lại để ngắt URL dài thành một vài dòng cho dễ đọc.

Liệt kê 4. Địa chỉ URL của nguồn cung cấp tin mẫu của Google Calendar với các tham số truy vấn
    http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/public/full?
    max-results=25&
    singleevents=true&
    orderby=starttime&
    start-min=2007-05-22T09%3A58%3A47-04%3A00&
    start-max=2007-11-06T09%3A58%3A47-04%3A00

Phân tích cú pháp nguồn cung cấp tin Google Calendar bằng PHP

Đến nay tôi đã thảo luận về các phần tử của nguồn cung cấp tin sự kiện của Google Calendar và cách truy vấn nguồn cung cấp tin này để nhận được các mục mà bạn đang quan tâm đến, tôi sẽ khảo sát kỹ các cách để phân tích cú pháp nguồn cung cấp tin này và hiển thị nó trên một trang. PHP cung cấp một số XML API mà bạn có thể sử dụng để lấy ra một danh sách các mục sự kiện và chọn ra các tên, ngày tháng, thời gian, và địa điểm cho mỗi sự kiện. Tôi sẽ bắt đầu với DOM API (Document Object Model – Mô hình đối tượng tài liệu).

Phân tích cú pháp nguồn cung cấp tin với DOM

XML DOM API là một API phân tích cú pháp-XML tiêu chuẩn, và nó được dùng phổ biến nhất khi lập trình các ứng dụng XML. Việc sử dụng DOM API nằm ngoài phạm vi của bài viết này, nhưng tôi sẽ xem xét kỹ một chương trình ví dụ để phân tích cú pháp một nguồn cung cấp tin sự kiện Google Calendar và giải thích một số lợi ích và hạn chế các DOM API.

Một lợi ích của XML DOM API là nó rất nhanh. Nó tải toàn bộ tài liệu XML vào trong bộ nhớ, và lấy ra các phần tử từ tất cả các tài liệu XML nằm ra trong bộ nhớ. Trong khi API này không hiệu quả với các tệp XML lớn, nó có thể chấp nhận được với các tệp XML chỉ có 2 hoặc 3 MB.

Một lợi ích khác của XML DOM API là khả năng dễ đọc của nó. Phân tích cú pháp XML với DOM có các lệnh để mở tài liệu XML và lấy ra các phần tử cụ thể từ các tài liệu theo kiểu phân cấp. Nó gần giống như tiếng Anh, nói với PHP "nhận được các phần tử với tên thẻ 'entry'". Liệt kê 5 là một ví dụ để giải thích điều tôi muốn nói.

Liệt kê 5. Phân tích cú pháp nguồn cung cấp tin sự kiện Google Calendar bằng DOM API
<?php 
    $confirmed = 'http://schemas.google.com/g/2005#event.confirmed';

    $three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
    $three_months_ago = date("Y-m-d\Th:i:sP", time() - $three_months_in_seconds);
    $three_months_from_today = date("Y-m-d\Th:i:sP", time() + $three_months_in_seconds);

    $feed = "http://www.google.com/calendar/feeds/foss.sanjuan%40gmail.com/" . 
        "public/full?orderby=starttime&singleevents=true&" . 
        "start-min=" . $three_months_ago . "&" .
        "start-max=" . $three_months_from_today;

    $doc = new DOMDocument(); 
    $doc->load( $feed );

    $entries = $doc->getElementsByTagName( "entry" ); 

    foreach ( $entries as $entry ) { 

        $status = $entry->getElementsByTagName( "eventStatus" ); 
        $eventStatus = $status->item(0)->getAttributeNode("value")->value;

        if ($eventStatus == $confirmed) {
            $titles = $entry->getElementsByTagName( "title" ); 
            $title = $titles->item(0)->nodeValue;

            $times = $entry->getElementsByTagName( "when" ); 
            $startTime = $times->item(0)->getAttributeNode("startTime")->value;
            $when = date( "l jS \o\f F Y - h:i A", strtotime( $startTime ) );

            $places = $entry->getElementsByTagName( "where" ); 
            $where = $places->item(0)->getAttributeNode("valueString")->value;

            print $title . "\n"; 
            print $when . " AST\n"; 
            print $where . "\n"; 
            print "\n"; 
        }
    }
?>

Trong ví dụ mã này, bạn thiết lập địa chỉ URL của nguồn cung cấp tin với các tham số cần thiết, mở nguồn cung cấp tin, sau đó nhận được tất cả các mục sự kiện trong một DOMNodeList, mà bạn có thể xử lý bằng trình lặp foreach. Với mỗi mục sự kiện, bạn so sánh giá trị thuộc tính của phần tử gd:eventStatus với giá trị đã biết với các sự kiện đã xác nhận. Lưu ý rằng bạn không cần chỉ rõ tiền tố gd: cho thẻ element. PHP DOM API hiểu các vùng tên, và bạn cần loại bỏ tiền tố gd: hoặc trình phân tích cú pháp sẽ không tìm thấy phần tử mà bạn cần.

Nếu mục sự kiện được xác nhận, bạn lấy ra các phần tử title, gd:whengd:where. Các phần tử gd:whengd:where đòi hỏi bạn đưa ra các thuộc tính cụ thể, ví dụ như startTimevalueString. Bạn muốn hiển thị các ngày sự kiện theo cách dễ đọc cho mọi người và phân tích cú pháp thuộc tính startTime của phần tử gd:when để chuyển đổi nó thành số nguyên dài biểu diễn thời gian. Sau đó, bạn chuyển các ngày sự kiện này tới hàm date theo định dạng hiển thị phổ biến.

Một trong những nhược điểm của DOM API là nó hơi dài dòng. Mặc dù mục đích của mỗi câu lệnh là rõ ràng những vì nó cần phù hợp với mô tả văn bản của thuật toán, nên câu lệnh không thể là một đoạn mã ngắn gọn hơn được. Các phương thức getElementsByTagNamegetAttributeNode với các lớp DOMNodeDOMDocument cũng làm tăng thêm kích thước đáng kể.

Phân tích cú pháp nguồn cung cấp tin với SAX

Một API phân tích cú pháp-XML có sẵn cho PHP là SAX API (Simple API for XML (SAX) API – API đơn giản cho XML API). Trong khi DOM API dễ đọc và dài dòng, thì SAX có thể ngắn gọn và khó thực hiện, ngay cả với các nhà phát triển có kinh nghiệm. Những khác biệt giữa SAX và DOM là SAX không tải toàn bộ tài liệu XML vào bộ nhớ, trong khi DOM làm như vậy. Mã xử lý SAX hiệu quả có thể có tốc độ nhanh, và có thể duy trì sử dụng bộ nhớ ở mức tối thiểu và phù hợp cho các nhu cầu cụ thể của ứng dụng. Với DOM, các yêu cầu bộ nhớ của bạn bắt đầu từ kích thước của tài liệu XML lớn nhất cần xử lý trong ứng dụng của bạn và từ đó tăng thêm.

Liệt kê 6 là một đoạn mã của một ví dụ về xử lý SAX của nguồn cung cấp tin sự kiện Google Calendar. Để có ví dụ hoàn chỉnh, hãy tham khảo kịch bản lệnh sax_sample.php trong gói các kịch bản lệnh ví dụ được cung cấp trong phần Tải về.

Liệt kê 6. Phân tích cú pháp nguồn cung cấp tin sự kiện Google Calendar bằng SAX API
    function startElement( $parser, $tagName, $attr )
    {
        global $g_entries, $g_tagName, $g_confirmed, $g_is_confirmed, 
            $g_in_entry, $g_in_originalevent;

        if ( $tagName == 'ENTRY' ) {
            if ($g_is_confirmed || count( $g_entries ) == 0) {
                $g_entries []= array();
            }
            $g_is_confirmed = false;
            $g_in_entry = true;
        }
        else if ($tagName == 'GD:EVENTSTATUS')
        {
            if ($attr['VALUE'] == $g_confirmed) {
                $g_is_confirmed = true;
            }
        }
        else if ($tagName == 'GD:WHEN' && $g_is_confirmed && 
            $g_in_originalevent == false)
        {
            $startTime = date( "l jS \o\f F Y - h:i A", strtotime($attr['STARTTIME']) );
            $g_entries[ count( $g_entries ) - 1 ]['when'] = $startTime;
        }
        else if ($tagName == 'GD:WHERE' && $g_is_confirmed)
        {
            $g_entries[ count( $g_entries ) - 1 ]['where'] = $attr['VALUESTRING'];
        }
        else if ( $tagName == 'GD:ORIGINALEVENT' ) {
            $g_in_originalevent = true;
        }
        $g_tagName = $tagName;
    }

    function endElement( $parser, $tagName ) 
    {
        global $g_tagName, $g_in_entry, $g_in_originalevent;

        if ( $tagName == 'ENTRY' ) {
            $g_in_entry = false;
        }
        else if ( $tagName == 'GD:ORIGINALEVENT' ) {
            $g_in_originalevent = false;
        }
        $g_tagName = null;
    }

    function textData( $parser, $text )
    {
        global $g_entries, $g_tagName, $g_in_entry;
        if ($g_tagName == 'TITLE' && $g_in_entry) {
            $g_entries[ count( $g_entries ) - 1 ]['title'] = $text;
        }
    }

Mã này cho thấy các hàm startElement, endElementtextData được đăng ký với máy của trình phân tích cú pháp SAX trong kịch bản lệnh ví dụ SAX. Phần mã này cho thấy việc xử lý với một số phần tử quan tâm. Mã là khá phức tạp vì trong SAX các phần tử XML của tài liệu XML được đọc theo thứ tự từ trên xuống dưới. Bạn không thể kiểm tra xem mục sự kiện hiện tại đã được xác nhận chưa trước khi bạn xử lý một số phần tử bạn muốn. Ví dụ, phần tử gd:eventStatus đặt sau phần tử title trong một sự kiện. Một nguồn khác phức tạp là nguồn cung cấp tin có phần tử title và mỗi mục cũng có một phần tử title. Bạn cần thiết lập một cờ để cho mã biết liệu bạn có đọc phần tử title trong mục đó không. Ngoài ra còn có phần tử gd:when bên trong phần tử gd:originalEvent trong các sự kiện định kỳ, không có phần tử gd:when mà bạn đang quan tâm. Nếu không có logic kiểm tra-trạng thái này, thì việc phối hợp đơn giản các tên phần tử sẽ tạo ra kết quả đầu ra sai.

Từ ví dụ này, bạn có thể thấy hai trong số các nhược điểm của SAX API: Nó dài dòng hơn nhiều so với DOM API và khi được so sánh với mã mẫu DOM, trình phân tích cú pháp SAX còn phức tạp hơn nhiều lần.

Phân tích cú pháp nguồn cung cấp tin với các trình bao Zend Google API

Zend Technologies, cộng tác với Google, đã mở rộng Khung công tác Zend (Zend Framework) để cung cấp một tập các lớp hướng đối tượng cho PHP, ẩn dấu nhiều thông tin chi tiết về các nguồn cung cấp tin Atom của API dữ liệu Google, trong khi vẫn đưa ra sự hỗ trợ cho tất cả thông tin dữ liệu của Google. Các lớp hướng đối tượng này có nhiều lợi ích, bao gồm việc trình bày các tài liệu API dữ liệu Google khác nhau như là các đối tượng trừu tượng với các phương thức và các tham số đơn giản và che giấu các thông tin chi tiết về các nguồn cung cấp tin Atom và các hành động của giao thức HTTP, như là các GET, các PUT và các POST. Các lớp này cũng chứa đựng các thông tin chi tiết về xác thực người dùng trong API dữ liệu Google, làm cho việc viết các ứng dụng hỗ trợ tất cả các tính năng của API dữ liệu Google trở nên đơn giản hơn, chẳng hạn như việc tạo và cập nhật các sự kiện từ một ứng dụng khách của bên thứ ba.

Trong khi điều này làm đơn giản hoá việc phát triển cho các nhà phát triển chưa quen với phân tích cú pháp XML và các thông tin chi tiết của giao thức HTTP, các lớp của API dữ liệu Google Zend Framework cũng có nhược điểm của mình. Như trong Liệt kê 7, mã này dài dòng vì nhiều hàm tạo đối tượng không có các tham số. Do đó, cần phải thiết lập các tùy chọn thông qua các đặc tính sau khi đã tạo ra một đối tượng.

Liệt kê 7. Yêu cầu và xử lý một nguồn cung cấp tin sự kiện Google Calendar với các lớp Zend PHP
<?php
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-d\Th:i:sP", time() - $three_months_in_seconds);
$three_months_from_today = date("Y-m-d\Th:i:sP", time() + $three_months_in_seconds);

// Create an instance of the Calendar service without authentication,
// for read-only access to a public feed
$service = new Zend_Gdata_Calendar();

$query = $service->newEventQuery();
$query->setUser('foss.sanjuan%40gmail.com');
$query->setVisibility('public');
$query->setProjection('full');
$query->setOrderby('starttime');
$query->setStartMin($three_months_ago);
$query->setStartMax($three_months_from_today);

// Retrieve the event list from the calendar server
try {
    $eventFeed = $service->getCalendarEventFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
    echo "Error: " . $e->getResponse();
}

// Iterate through the list of events, outputting them as an HTML list
print "<ul>\n";
foreach ($eventFeed as $event) {
    print "<li>" . $event->title . "</li>\n";

	$startTime = $event->when->startTime;
    print "<li>" . date("l jS \o\f F Y - h:i A", strtotime( $startTime ) );

	// Google Calendar API's support of timezones is buggy
    print " AST</li>\n";

    print "<li>" . $event->where->valueString . "</li>\n";
}
print "</ul>\n";

Một trong những lợi ích của các lớp API dữ liệu Google Zend là sau khi đối tượng eventFeed được lấy ra, các phần tử và các thuộc tính của nguồn cung cấp tin có thể được duyệt theo phân cấp như các thuộc tính của đối tượng eventFeed. Theo ý kiến của tôi, việc này cho phép dễ đọc mã xử lý hơn vì các phần tử khác nhau được thiết lập theo mẫu tương tự như cách chúng được trình bày trong tài liệu XML. Các thuộc tính cũng có khả năng duyệt theo kiểu phân cấp từ các phần tử cha mẹ của chúng, không giống như phương thức getAttributeNode("attributeName")->value của DOMNode.


Phân tích cú pháp với XPath và SimpleXML

Tôi tin rằng SimpleXML API, với sự hỗ trợ của nó để truy vấn tài liệu XML bằng cách sử dụng XPath, là một trong những API phân tích cú pháp-XML đơn giản nhất để sử dụng. Nó chứa tài liệu XML như là một tập các đặc tính đối tượng có phân cấp của tài liệu XML được tải. API này cũng tương tự như cách DOM trả về các cá thể của đối tượng DOMNode, có thể duyệt theo phân cấp. Giống như các đối tượng DOMNode của DOM và không giống như các lớp Zend, các thuộc tính của một phần tử cần được lấy ra bằng cách gọi phương thức attributes(). Phương thức này trả về một đối tượng chứa các thuộc tính như là các đặc tính đối tượng. Liệt kê 8 nêu ra tất cả các logic cần thiết để phân tích cú pháp và duyệt một nguồn cung cấp lịch của API dữ liệu Google bằng SimpleXML.

Liệt kê 8. Phân tích cúa pháp nguồn cung cấp tin sự kiện Google Calendar với XPath và SimpleXM
    $s = simplexml_load_file($feed); 

    foreach ($s->entry as $item) {
        $gd = $item->children('http://schemas.google.com/g/2005');

        if ($gd->eventStatus->attributes()->value == $confirmed) {
?>
            <font size=+1><b>
                <?php print $item->title; ?>
            </b></font><br>

<?php 
            $startTime = '';
            if ( $gd->when ) {
                $startTime = $gd->when->attributes()->startTime;
            } elseif ( $gd->recurrence ) {
                $startTime = $gd->recurrence->when->attributes()->startTime; 
            } 

            print date("l jS \o\f F Y - h:i A", strtotime( $startTime ) );
            // Google Calendar API's support of timezones is buggy
            print " AST<br>";
?>
            <?php print $gd->where->attributes()->valueString; ?>
            <br><br>

<?php
        }
    } ?>

Một nhược điểm với SimpleXML API của PHP là nó có thể chậm hơn nhiều nhất đến bốn lần so với DOM hoặc SAX. Điều này xuất phát từ thực tế là SimpleXML tạo các nút phần tử và thuộc tính trong lúc hoạt động bằng cách lợi dụng tính chất động của PHP. Ngược lại các lớp API dữ liệu Google Zend, định nghĩa các nút phần tử và thuộc tính trong mã lớp. Điều này làm cho việc duyệt các nút theo phân cấp bằng các lớp Zend nhanh hơn.

Một nhược điểm nữa với SimpleXML là sự hỗ trợ của nó cho các vùng tên XML. Để lấy ra các phần tử từ một vùng tên, cần gọi phương thức children() trên một phần tử. Phương thức này trả về một đối tượng có các phần tử của vùng tên đó làm các đặc tính. DOM và các lớp Zend cung cấp hỗ trợ tốt hơn bằng cách đưa ra tất cả các phần tử của tất cả các vùng tên làm các nút có thể duyệt-theo phân cấp riêng lẻ của các phần tử khác.


Xem xét hiệu năng và lưu trữ trong bộ nhớ nhanh

Khi thảo luận về phân tích cú pháp XML trong PHP, tôi đã nói rằng SimpleXML có thể chậm hơn nhiều lần so với việc phân tích cú pháp DOM hoặc SAX. Lý do để chọn SimpleXML của tôi là nó dễ sử dụng hơn so với SAX và làm cho mã phân tích cú pháp XML dễ đọc hơn DOM. Việc tạo các nút phần tử và thuộc tính của SimpleXML trong lúc hoạt động như là các đặc tính của các nút khác làm cho mã duyệt nút hầu như dễ đọc như các lớp API dữ liệu Google Zend.

Tuy nhiên, mẫu mã được cung cấp trong bài viết này có vấn đề khác: Nó đòi hỏi nguồn cung cấp tin sự kiện Google Calendar mỗi khi người dùng truy cập vào trang đó. Nếu bạn đặt mẫu mã này vào một thanh bên trên một trang PHP, thì mỗi khi một người truy cập vào bất kỳ các trang nào của bạn, mã này phải tải về và phân tích cú pháp nguồn cung cấp tin. Việc này là khá lãng phí, nếu xét ra lịch có thể không thay đổi hàng giờ hoặc thậm chí hàng ngày. Nếu trang của bạn là phổ biến và thu hút 1000 hoặc nhiều lần truy cập trang hơn cho mỗi ngày (dễ dàng đạt được với một diễn đàn phổ biến chỉ với nhóm 20-30 người dùng), nguồn cung cấp tin này được yêu cầu và được xử lý với mỗi lần truy cập trang. API dữ liệu Google có các điều khoản dịch vụ rõ ràng giải thích rằng kiểu sử dụng này là không được phép. Google có thể, và có lẽ, sẽ chặn địa chỉ IP của máy chủ của bạn nếu bạn lạm dụng các điều khoản dịch vụ của nó. Tệ hơn nữa, Google có thể hủy bỏ tài khoản của bạn. Rõ ràng, cần một cách tiếp cận thông minh hơn.

Có một vài chiến lược mà bạn có thể thực hiện để tạo cho mã mẫu này làm việc thông minh hơn và trong phạm vi các điều khoản dịch vụ của Google API. Tất cả đều liên quan đến việc lưu trữ thông tin cần hiển thị trong bộ nhớ nhanh theo kịch bản lệnh và chỉ yêu cầu xử lý toàn bộ nguồn cung cấp tin nếu và khi nó đã thay đổi. Một cuộc thảo luận chuyên sâu về các kỹ thuật lưu trữ trong bộ nhớ nhanh nằm ngoài phạm vi của bài viết này, nhưng tôi sẽ trình bày chúng rất ngắn gọn để cung cấp cho bạn một ý tưởng về cách có thể cải thiện kịch bản lệnh này.

Một kỹ thuật liên quan đến việc sử dụng HTTP đòi hỏi các tiêu đề kiểm tra xem nguồn cung cấp tin API dữ liệu Google đã thay đổi chưa. Các dịch vụ dữ liệu Google thiết lập tiêu đề đáp ứng Last-Modified dựa trên giá trị của phần tử <atom:updated> trong thông tin được trả về. Kịch bản lệnh, dựa vào lần gọi đầu tiên, có thể lưu trữ kết quả đầu ra được tạo bằng cách xử lý nguồn cung cấp tin với một tệp HTML. Sau đó kịch bản lệnh này có thể lưu giá trị của dấu thời gian <atom:updated> trong một bản ghi cơ sở dữ liệu. Tiếp theo bất kỳ người dùng nào yêu cầu xem lịch sự kiện, máy khách lấy ra dấu thời gian này và gửi nó trở lại vào tiêu đề yêu cầu If-Modified-Since để tránh lấy lại nguồn cung cấp tin nếu nó vẫn chưa thay đổi.

Nếu nội dung vẫn không thay đổi kể từ thời điểm được chỉ thị trong tiêu đề If-Modified-Since, dịch vụ dữ liệu Google trả về một đáp ứng HTTP 304 (Not Modified không thay đổi). Vì đáp ứng này có nghĩa là dữ liệu sự kiện vẫn chưa thay đổi, sau đó kịch bản lệnh có thể bao gồm tệp HTML được tạo ra trước đó. Nếu nguồn cung cấp tin đã thay đổi, dịch vụ dữ liệu Google trả về một đáp ứng HTTP 200 (OK). Trong trường hợp này, kịch bản lệnh tái tạo nội dung mới cho tệp HTML, thiết lập bản ghi cơ sở dữ liệu với giá trị dấu thời gian mới trong phần tử <atom:updated>bao gồm tệp HTML mới được tạo ra.

Việc lưu một dấu thời gian đơn lẻ vào một cơ sở dữ liệu đúng là hơi quá mức một chút, nhưng PHP không hỗ trợ các biến mức-ứng dụng như các ASP (Active Server Pages – Các trang máy chủ hoạt động) của Microsoft, Microsoft ASP.NET, các Java servlet và các trang JavaServer (JSP) làm, ít nhất là không có sẵn trong gói. Một giải pháp tương tự là sử dụng bộ nhớ chia sẻ. Không phải tất cả các bản cài đặt PHP đều hỗ trợ bộ nhớ chia sẻ vì đó có thể là một nguy cơ an toàn. Lựa chọn lưu trữ trong bộ nhớ nhanh có khả năng khác, đặc biệt là nếu ứng dụng PHP của bạn đang chạy trong một cụm máy chủ Web, là memcached, một dịch vụ lưu trữ-bộ nhớ có phân cụm ban đầu được viết bởi các tác giả của LiveJournal và bây giờ được cải thiện rộng rãi bởi các nhà phát triển của Facebook.


Kết luận

Google Calendar cung cấp một lối vào ứng dụng Web tập trung từ đó một tổ chức và các nhà lãnh đạo của nó có thể duy trì và xuất bản một lịch sự kiện cho các thành viên và công chúng nói chung. API dữ liệu Google đưa ra các nguồn cung cấp tin Atom và Giao thức xuất bản Atom để lấy ra, truy vấn, cập nhật, và tạo ra các sự kiện và các thông tin khác bằng Google Calendar và hầu như tất cả các ứng dụng Google khác.

Sử dụng XPath, bạn có thể tự động duy trì hiển thị trang Web với các sự kiện sắp tới theo ngày bằng cách truy vấn các nguồn cung cấp tin sự kiện API dữ liệu Google và phân tích cú pháp các mục của nó với các thông tin chi tiết có liên quan giữa các phần tử của các mục. Trong khi XPath không phải là XML API nhanh nhất trong bộ công cụ PHP, thì nó là một trong những API đơn giản nhất để sử dụng khi bạn có một tài liệu XML đầy đủ trên tay. Bạn có thể sử dụng lưu trữ trong bộ nhớ nhanh để giảm tác động về hiệu năng tương đối chậm của XPath.


Tải về

Mô tảTênKích thước
Sample PHP codeos-php-xpath.google-calendar-api.zip4KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=777359
ArticleTitle=Hiển thị các sự kiện Google Calendar trên trang Web PHP của bạn với XPath
publish-date=11302011