XML dành cho các nhà phát triển PHP, Phần 3: Các kỹ thuật nâng cao để đọc, thao tác và viết XML

Thêm XSLT vào các API DOM và SimpleXML

Bài cuối cùng trong loạt bài ba phần này bàn luận về nhiều kỹ thuật hơn để đọc, thao tác và viết XML bằng PHP5. Trong đó bạn sẽ tập trung vào các API DOM và SimpleXML giờ đã thành quen thuộc trong các điều kiện phức tạp hơn, và lần đầu tiên trong loạt bài ba phần này, tập trung vào phần mở rộng XSL.

Cliff Morgan, Tác giả, 自由职业者

Cliff Morgan là một nhà tư vấn độc lập, người thiết kế và thực hiện các ứng dụng Web và các điểm Web.



22 01 2011

Giới thiệu

PHP5 cung cấp cho các nhà phát triển nhiều sức mạnh hơn để làm việc với XML. Các phần mở rộng mới và cải biên như DOM, SimpleXML và XSL làm cho bớt phải viết mã hơn khi làm việc với XML. Trong PHP5, DOM tương thích với chuẩn W3C. Quan trọng nhất là tính liên tác giữa các phần mở rộng này là đáng kể, cung cấp chức năng bổ sung, như các định dạng tráo đổi để mở rộng tính khả dụng, XPath của W3C, và nhiều hơn nữa, áp dụng với tất cả. Ở đây bạn sẽ xem xét các tuỳ chọn nhập và xuất, và bạn sẽ tuỳ thuộc vào giao diện giao thức REST Các Dịch vụ Yahoo Web để cung cấp một tủ trưng bày tinh vi hơn đối với chức năng của DOM và phần mở rộng SimpleXML giờ đã trở nên quen thuộc và kết thúc với phần mở rộng XSL.


Trong loạt bài này trước đây

Bài viết đầu tiên của loạt bài này đã cung cấp các thông tin cốt yếu về XML. Nó tập trung vào các giao diện lập trình ứng dụng (API) khởi động nhanh và giải thích tại sao SimpleXML, kết hợp với Mô hình Đối tượng Tài liệu (DOM) khi cần thiết, là sự lựa chọn lý tưởng nếu bạn làm việc với các tài liệu XML không phức tạp, có thể đoán trước được, và tương đối cơ bản. Phần 2 xem xét theo bề rộng các API phân tích cú pháp có sẵn cho XML trong PHP5, gồm có SimpleXML, DOM, API đơn giản dùng cho XML (SAX), và XMLReader và cân nhắc xem các kỹ thuật phân tích nào là thích hợp nhất đối với các kích thước và độ phức tạp khác nhau của các tài liệu XML.

XML trong PHP5

Ngôn ngữ Đánh dấu Mở rộng (XML), được mô tả vừa như là một ngôn ngữ đánh dấu, vừa như là một định dạng lưu trữ dữ liệu dựa trên văn bản, cung cấp một phương tiện dựa trên văn bản để áp dụng và mô tả một cấu trúc hình cây cho thông tin. Ở đây bạn sẽ xem xét XML trong ngữ cảnh các dịch vụ Web, rất có thể là một trong những nhân tố quan trọng nhất thúc đẩy sự tăng trưởng gần đây của XML bên ngoài thế giới ứng dụng doanh nghiệp.

Trong PHP5, có các phần mở rộng hoàn toàn mới và được viết lại hoàn toàn để thao tác XML, tất cả dựa trên cùng một bộ mã libxml2. Nền móng chung này cung cấp sự liên tác giữa các phần mở rộng ấy và nó mở rộng thêm chức năng của từng phần. Các bộ phân tích cú pháp dựa trên cấu trúc cây bao gồm SimpleXML, DOM, và bộ xử lý XSLT. Nếu bạn đã quen với DOM từ các ngôn ngữ khác, bạn sẽ dễ dàng viết mã với các chức năng tương tự bằng PHP hơn trước đây. Các bộ phân tích cú pháp dựa trên luồng gồm có API Đơn giản dùng cho XML (SAX) và XMLReader. SAX hoạt động cùng một cách như trước đây trong PHP4.


Thao tác XML bằng cách sử dụng DOM

Bạn có thể sử dụng DOM để thao tác một tệp tin XML. Việc sử dụng DOM có hiệu quả chỉ khi nào tệp tin XML là tương đối nhỏ. Các ưu điểm của việc sử dụng phương thức này là các tiêu chuẩn vững chắc của W3C DOM quen thuộc, các phương thức của nó, và tính linh hoạt mà nó đem lại cho việc mã hóa. Các nhược điểm của DOM là sự khó khăn trong việc mã hóa và các vấn đề về hiệu năng với các tài liệu lớn.


DOM vào việc

Với DOM, bạn có thể xây dựng nên, sửa đổi, truy vấn, xác nhận hợp lệ và chuyển đổi các tài liệu XML. Tất cả các phương thức và đặc tính của DOM có thể sử dụng được, và hầu hết các phương thức DOM mức 2 được thực hiện với các thuộc tính được hỗ trợ chính xác. Các tài liệu được phân tích bằng DOM có thể phức tạp tùy ý vì tính vô cùng linh hoạt của nó. Tuy nhiên phải nhớ rằng tính linh hoạt đó có cái giá của nó nếu bạn nạp một tài liệu XML lớn vào bộ nhớ cùng một lúc.

Các thí dụ trong bài viết này sử dụng API tìm kiếm của Yahoo, PHP5, và REpresentational State Transfer (REST) để minh họa việc sử dụng DOM trong một môi trường ứng dụng thú vị. Yahoo đã chọn REST vì các nhà phát triển tin chắc rằng REST cung cấp 80% lợi ích của SOAP chỉ với 20% chi phí. Tôi đã chọn ứng dụng này để trình diễn PHP/XML vì tính phổ biến của dịch vụ Web rất có thể là một trong những nhân tố quan trọng nhất thúc đẩy sự tăng trưởng gần đây của XML bên ngoài thế giới ứng dụng doanh nghiệp.

Thường thì REST tạo ra một yêu cầu bằng cách bắt đầu với một mục URL dịch vụ và sau đó nối thêm vào các tham số tìm kiếm dưới dạng một chuỗi truy vấn.Liệt kê 1 phân tích các kết quả của truy vấn này bằng cách sử dụng phần mở rộng DOM.

Liệt kê 1. Mã mẫu trình diễn của Yahoo sử dụng DOM
<?php

//This query does a search for any Web pages relevant to "XML Query"
$query = "http://api.search.yahoo.com/WebSearchService/V1/webSearch?".
         "query=%5C%22XML%20Query%5C%22&appid=YahooDemo";

//Create the DOM Document object from the XML returned by the query
$xml = file_get_contents($query);
$dom = new DOMDocument;
$dom = DOMDocument::loadXML($xml);

function xml_to_result($dom) {

  //This function takes the XML document and maps it to a
  //PHP object so that you can manipulate it later.

  //First, retrieve the root element for the document
  $root = $dom->firstChild;

  //Next, loop through each of its attributes
  foreach($root->attributes as $attr) {
    $res[$attr->name] = $attr->value;
  }

  //Now, loop through each of the children of the root element
  //and treat each appropriately.

  //Start with the first child node.  (The counter, i, is for
  //tracking results.
  $node = $root->firstChild;
  $i = 0;

  //Now keep looping through as long as there is a node to work
  //with.  (At the bottom of the loop, the code moves to the next
  //sibling, so when it runs out of siblings, the routine stops.
  while($node) {

    //For each node, check to see whether it's a Result element or
    //one of the informational elements at the start of the document.
    switch($node->nodeName) {

      //Result elements need more analysis.
      case 'Result':
        //Add each child node of the Result to the result object,
        //again starting with the first child.
        $subnode = $node->firstChild;
        while($subnode) {

          //Some of these nodes just are just whitespace, which does
          //not have children.
          if ($subnode->hasChildNodes()){

            //If it does have children, get a NodeList of them, and
            //loop through it.
            $subnodes = $subnode->childNodes;
            foreach($subnodes as $n) {

              //Again check for children, adding them directly or
              //indirectly as appropriate.
              if($n->hasChildNodes()) {
                foreach($n->childNodes as $cn){
                   $res[$i][$subnode->nodeName][$n->nodeName]=
                                              trim($cn->nodeValue);
                }
            } else {
                $res[$i][$subnode->nodeName]=trim($n->nodeValue);
              }
            }
          }
          //Move on to the next subnode.
          $subnode = $subnode->nextSibling;
        }
        $i++;
        break;
      //Other elements are just added to the result object.
      default:
        $res[$node->nodeName] = trim($node->nodeValue);
        break;
    }

    //Move on to the next Result of informational element
    $node = $node->nextSibling;
  }
  return $res;
}

//First, convert the XML to a DOM object you can manipulate.
$res = xml_to_result($dom);

//Use one of those "informational" elements to display the total
//number of results for the query.
echo "<p>The query returns ".$res["totalResultsAvailable"].
            " total results  The first 10 are as follows:</p>";

//Now loop through each of the actual results.
for($i=0; $i<$res['totalResultsReturned']; $i++) {

    echo "<a href='".$res[$i]['ClickUrl']."'><b>".
                            $res[$i]['Title']."</b></a>:  ";
    echo $res[$i]['Summary'];

    echo "<br /><br />";
}

?>

Thao tác XML bằng cách sử dụng SimpleXML

Phần mở rộng SimpleXML là một công cụ đáng lựa chọn để thao tác một tài liệu XML, với điều kiện là tài liệu XML đó không quá phức tạp hoặc quá sâu, và không chứa nội dung hỗn tạp. SimpleXML dễ mã hoá hơn DOM, như tên của nó hàm ý. Nó trực quan hơn rất nhiều nếu bạn làm việc với một cấu trúc tài liệu đã biết. Trong khi gia tăng rất nhiều mức độ linh hoạt của DOM và SimpleXML, bản chất liên tác của kiến trúc libXML2 sẽ cho phép nhập khẩu để tráo đổi các định dạng từ DOM thành SimpleXML và ngược lại tuỳ ý muốn.

SimpleXML vào việc

Các tài liệu được thao tác với SimpleXML thì mã hoá đơn giản và nhanh chóng. Mã sau đây phân tích các kết quả của truy vấn bằng cách sử dụng phần mở rộng SimpleXML. Như bạn hẳn mong đợi, mã SimpleXML sau đây (xem Liệt kê 2) nhỏ gọn hơn so với mã mẫu DOM đã thấy ở trên trong Liệt kê 1.

Liệt kê 2. Ví dụ SimpleXML của Yahoo
<?php

//This query does a search for any Web pages relevant to "XML Query"
$query = "http://api.search.yahoo.com/WebSearchService/V1/webSearch?".
         "query=%5C%22XML%20Query%5C%22&appid=YahooDemo";

$xml = simplexml_load_file($query);

// Load up the root element attributes
foreach($xml->attributes() as $name=>$attr) {
   $res[$name]=$attr;
}

//Use one of those "informational" elements to display the total
//number of results for the query.
echo "<p>The query returns ".$res["totalResultsAvailable"].
            " total results  The first 10 are as follows:</p>";

//Unlike with DOM, where we loaded the entire document into the
//result object, with SimpleXML, we get back an object in the
//first place, so we can just use the number of results returned
//to loop through the Result members.

for($i=0; $i<$res['totalResultsReturned']; $i++) {

    //The object represents each piece of data as a member variable
    //rather than an array element, so the syntax is a little bit
    //different from the DOM version.

    $thisResult = $xml->Result[$i];

    echo "<a href='".$thisResult->ClickUrl."'><b>".
                       $thisResult->Title."</b></a>:  ";
    echo $thisResult->Summary;

    echo "<br /><br />";
}

?>

Liệt kê 3 bổ sung một tầng nhớ đệm vào ví dụ mẫu SimpleXML trong Liệt kê 2. Tầng nhớ đệm đưa vào bộ nhớ các kết quả của bất kỳ truy vấn cụ thể nào trong hai giờ đồng hồ.

Liệt kê 3. Mẫu SimpleXML với một tầng nhớ đệm của Yahoo
<?php

//This query does a search for any Web pages relevant to "XML Query"
$query = "http://api.search.yahoo.com/WebSearchService/V1/webSearch?".
         "query=%5C%22XML%20Query%5C%22&appid=YahooDemo";

//The cached material should only last for 2 hours, so you need the
//current time.
$currentTime = microtime(true);

//This is where I put my tempfile; you can store yours in a more
//convenient location.
$cache = 'c:\temp\yws_'.md5($query);

//First check for an existing version of the time, and then check
//to see whether or not it's expired.
if(file_exists($cache) &&
          filemtime($cache) > (time()-7200)) {

   //If there's a valid cache file, load its data.
   $data = file_get_contents($cache);
} else {

   //If there's no valid cache file, grab a live version of the
   //data and save it to a temporary file.  Once the file is complete,
   //copy it to a permanent file.  (This prevents concurrency issues.)
   $data = file_get_contents($query);
   $tempName = tempnam('c:\temp','YWS');
   file_put_contents($tempName, $data);
   rename($tempName, $cache);
}

//Wherever the data came from, load it into a SimpleXML object.
$xml = simplexml_load_string($data);

//From here, the rest of the file is the same.

// Load up the root element attributes
foreach($xml->attributes() as $name=>$attr) {
   $res[$name]=$attr;
}

...

Thao tác XML bằng cách sử dụng XSL

Ngôn ngữ tờ kiểu dáng mở rộng (XSL - Extensible Stylesheet Language) là một ngôn ngữ XML được tạo ra cho các tác vụ thao tác các tài liệu XML. Bằng cách sử dụng XSL, bạn có thể chuyển một tài liệu XML thành một tài liệu XML được định nghĩa lại, thành một tài liệu XHTML, thành một tài liệu HTML, hoặc một tài liệu văn bản dựa trên một định nghĩa tờ kiểu dáng tương tự như cách mà CSS làm việc bằng cách thực hiện các quy tắc. Việc thực hiện chuẩn W3C của PHP5 hỗ trợ sự liên tác với DOM và XPath. Các phép chuyển đổi ngôn ngữ tờ kiểu dáng mở rộng (XSLT) là một phần mở rộng XML dựa trên libxml2, và các tờ kiểu dáng của nó cũng là các tài liệu XML. XSLT chuyển đổi một cây nguồn XML thành một cây kết quả XML hoặc kiểu XML. Các phép chuyển đổi này áp dụng chuỗi các quy tắc quy định trong tờ kiểu dáng đối với dữ liệu XML. XSLT có thể thêm vào hoặc bỏ bớt đi các phần tử hoặc thuộc tính của tệp tin đầu ra. Nó cho phép nhà phát triển sắp xếp hoặc sắp xếp lại các phần tử và quyết định phần tử nào sẽ ẩn hoặc hiển thị. Các tờ kiểu dáng khác nhau cho phép tài liệu XML của bạn hiển thị một cách thích hợp cho các phương tiện truyền thông khác nhau, chẳng hạn như hiển thị trên màn hình so với hiển thị khi in ra. XSLT sử dụng XPath để dẫn hướng trong tài liệu XML gốc. Mô hình chuyển đổi XSLT thường liên quan đến một tệp tin XML nguồn, một tệp tin XSLT chứa một hoặc nhiều khuôn mẫu xử lý, và một bộ xử lý XSLT. Các tài liệu XSLT phải được nạp bằng cách sử dụng DOM. PHP5 chỉ hỗ trợ bộ xử lý libxslt.

XSL vào việc

Một ứng dụng thú vị của XSL là tạo ra các tệp tin XML khi đang chạy để chứa bất cứ dữ liệu nào vừa được chọn ra từ cơ sở dữ liệu. Với việc sử dụng kỹ thuật này, có thể tạo ra các ứng dụng Web hoàn chỉnh, ở đây các kịch bản lệnh PHP được làm từ các tệp tin XML từ các truy vấn cơ sở dữ liệu, sau đó sử dụng các phép chuyển đổi XSL để tạo ra các tài liệu HTML thực tế.

Phương thức này tách rời hoàn toàn tầng trình diễn khỏi tầng xử lý nghiệp vụ để bạn có thể bảo trì cả hai lớp này độc lập nhau.

Liệt kê 4 minh họa mối quan hệ giữa tệp tin XML đầu vào, tờ kiểu dáng XSL, bộ xử lý XSLT, và nhiều kết quả đầu ra có thể.

Liệt kê 4. Chuyển đổi XML
<?php

// Create new XSLTProcessor
$xslt = new XSLTProcessor();

//Both the source document and the stylesheet must be
//DOMDocuments, but the result can be a DOMDocument,
//a file, or even a String.

// Load the XSLT stylesheet
$xsl = new DOMDocument();
$xsl->load('recipe.xsl');

// Load the stylesheet into the processor
$xslt->importStylesheet($xsl);

// Load XML input file
$xml = new DOMDocument();
$xml->load('recipe.xml');

//Now choose an output method and transform to it:

// Transform to a string
$results = $xslt->transformToXML($xml);
echo "String version:";
echo htmlentities($results);

// Transform to DOM object
$results = $xslt->transformToDoc($xml);
echo "The root of the DOM Document is ";
echo $results->documentElement->nodeName;

// Transform to a file
$results = $xslt->transformToURI($xml, 'results.txt');

?>

Tóm tắt

Các phần trước của loạt bài này đã tập trung vào việc sử dụng Mô hình Đối tượng Tài liệu (DOM) và SimpleXML để thực hiện các nhiệm vụ phân tích cú pháp cả đơn giản lẫn phức tạp. Phần 2 cũng xem xét việc sử dụng XMLReader, nó cung cấp một cách dễ hơn và nhanh hơn để thực hiện các nhiệm vụ mà trước đây được thực hiện bằng cách sử dụng SAX.

Bây giờ, trong bài viết này bạn đã thấy cách làm thế nào truy cập từ xa các tệp tin chẳng hạn như các dịch vụ Web dựa trên REST, và cách sử dụng XSLT để dễ dàng xuất dữ liệu XML thành một chuỗi ký tự, đối tượng Tài liệu DOM, hoặc tệp tin.

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=619074
ArticleTitle=XML dành cho các nhà phát triển PHP, Phần 3: Các kỹ thuật nâng cao để đọc, thao tác và viết XML
publish-date=01222011