Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan, Phần 4: Các phép biến đổi XML

Chuyển đổi, tìm kiếm, duyệt đi qua và định dạng dữ liệu XML của bạn

Khi một ứng dụng muốn chia sẻ dữ liệu với các hệ thống khác, thông thường cần biến đổi một tài liệu XML thành một định dạng XML khác, được một Lược đồ XML (XML Schema) hoặc Document Type Definition (DTD- Định nghĩa kiểu tài liệu) khác nhau chi phối. Khi một ứng dụng được yêu cầu chia sẻ hoặc hiển thị dữ liệu XML cho một người sử dụng, tài liệu XML có thể được biến đổi sang dạng HTML, Scalable Vector Graphics (SVG-Các đồ họa vec tơ căn chỉnh được), VoiceXML, văn bản thuần hay bất kỳ một trong số rất nhiều các định dạng để con người có thể đọc được. Hướng dẫn này bàn về các phép biến đổi XML và là phần thứ tư trong một loạt bài gồm có năm hướng dẫn mà bạn có thể sử dụng để trợ giúp chuẩn bị làm Bài kiểm tra cấp chứng chỉ IBM số 142, XML và các công nghệ liên quan.

Brian L Brinker, Chuyên viên IT cao cấp, IBM

Brian L. Brinker đã nghiên cứu về các phép biến đổi XML bằng cách trợ giúp thiết kế và xây dựng một ứng dụng tạo nguyên mẫu (prototyping) dựa trên XML, đó là IBM® WebSphere Portal Experience Modeler (Trình mô hình hóa kinh nghiệm Portal WebSphere của IBM). Brian làm việc tại các trung tâm của IBM về Đổi mới Giải pháp (Atlanta, Georgia). Ông có các bằng cấp về vật lý, khoa học máy tính và quản lý các hệ thống thông tin; ông sống với vợ và con trai của mình ở vùng đồi chân núi Appalachian tuyệt đẹp của Jasper, Georgia.



11 12 2009

Trước khi bạn bắt đầu

Trong phần này, bạn sẽ tìm hiểu có thể học được những gì từ hướng dẫn này và làm thế nào để thu nhận được nhiều nhất từ nó.

Về loạt bài viết này

Loạt bài viết này gồm năm hướng dẫn giúp bạn chuẩn bị để làm Bài kiểm tra 142 lấy chứng chỉ IBM, XML và các công nghệ liên quan, để đạt chứng chỉ Nhà phát triển giải pháp có chứng nhận của IBM - XML và các công nghệ liên quan. Chứng chỉ này xác nhận một nhà phát triển trình độ mức trung cấp, người thiết kế và triển khai thực hiện các ứng dụng có sử dụng XML và các công nghệ liên quan như: Lược đồ XML, Extensible Stylesheet Language Transformation (XSLT- Chuyển đổi ngôn ngữ phiếu định kiểu mở rộng) và XPath. Nhà phát triển này có một sự hiểu biết tốt về XML cơ bản, có kiến thức về các khái niệm của XML và các công nghệ liên quan; hiểu dữ liệu tương quan với XML như thế nào, đặc biệt là với các vấn đề kết hợp với việc mô hình hóa thông tin, xử lý XML, biểu hiện XML và các dịch vụ Web; có một kiến thức uyên thâm về các khuyến cáo W3C có liên quan đến XML cốt lõi; và quen thuộc với các cách làm thực hành tốt nhất, được nhiều người biết đến.

Về hướng dẫn này

Đây là hướng dẫn thứ tư trong loạt bài "Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan", nó tập trung vào các phép biến đổi XML. Nó mô tả chi tiết làm thế nào để làm cho dữ liệu nổi lên trong các tài liệu XML theo nhiều cách. Nó thừa nhận và xây dựng dựa trên nền móng trình bày trong Phần 3, trong đó tập trung vào việc xử lý XML và cũng có trong Phần 2, trong đó đã thảo luận việc xác nhận hợp lệ của XML thông qua DTD và XML Schema (xem Tài nguyên). Không có nền tảng cơ sở này, các phép biến đổi XML sẽ không thể thực hiện được.

Hướng dẫn này được viết cho các lập trình viên và người viết kịch bản lệnh, những người có một sự hiểu biết cơ bản về XML và các kỹ năng và kinh nghiệm của họ ở mức bắt đầu đến mức trung cấp. Như vậy, bạn cần phải có hiểu biết chung về các kiểu dữ liệu, bao gồm các mảng, các đồ thị và đặc biệt là các cây. Bạn cũng nên quen thuộc với các kỹ thuật lập trình chung như: phép lặp và đệ quy. Mặc dù hướng dẫn này bắt đầu với những điều căn bản về các công nghệ được thảo luận, nó không nhằm mục tiêu trở thành tài liệu tham khảo toàn diện. Tuy nhiên, nếu được nghiên cứu kỹ, hướng dẫn này, được kết hợp với các tài liệu tham khảo trong Tài nguyên, sẽ cung cấp đủ rộng và đủ sâu để làm chủ các khía cạnh của phép biến đổi XML cho kỳ thi cấp chứng chỉ XML.

Các mục tiêu

Sau khi hoàn thành hướng dẫn này, bạn sẽ:

  • Hiểu cách làm thế nào sử dụng XSLT để biến đổi XML.
  • Có khả năng thực hiện các phép tính toán học và chuỗi ký tự để tìm kiếm và duyệt đi qua XML bằng Xpath.
  • Biết cách làm thế nào để định dạng trực quan XML bằng CSS.

Các điều kiện cần trước

Hướng dẫn này được viết cho các nhà phát triển, những người có một kiến thức nền tảng về lập trình và kịch bản lệnh và những người có một sự hiểu biết về các mô hình khoa học máy tính cơ bản và các cấu trúc dữ liệu. Bạn cần quen thuộc với các khái niệm khoa học máy tính, có liên quan đến XML sau đây: duyệt đi qua cây, phép đệ quy, và sử dụng lại dữ liệu. Bạn cũng cần quen biết với các tiêu chuẩn và các khái niệm Internet, chẳng hạn như trình duyệt Web, mô hình khách-chủ, dẫn chứng bằng tài liệu, định dạng, thương mại điện tử và các ứng dụng web.

Các yêu cầu hệ thống

Như trong Phần 3 của loạt bài này, bạn cần một máy tính chạy Linux® hay Microsoft® Windows® với ít nhất 50MB dung lượng đĩa trống và quyền truy cập quản trị để cài đặt phần mềm. Hướng dẫn này sử dụng, nhưng không bắt buộc là, các phần mềm sau đây:

  • Altova XMLSpy (Ấn bản gia đình miễn phí sẽ là đủ).
  • Trình duyệt Internet Explorer của Microsoft™, phiên bản 6.0 hoặc cao hơn.
  • Mozilla Firefox, phiên bản 1.0.7 hoặc cao hơn.

Xin lưu ý rằng các tài liệu XSLT là XML và do đó có thể được chỉnh sửa bằng bất kỳ trình soạn thảo văn bản nào, như Microsoft Notepad hoặc Vim. Tuy nhiên sẽ rất có ích nếu trình soạn thảo của bạn có khả năng hỗ trợ bạn trong việc làm cho các tài liệu của bạn đúng khuôn dạng; XMLSpy có thể làm được điều này và nhiều hơn nữa. Tài liệu CSS không theo đúng ngữ pháp và cú pháp của XML, do đó, xin vui lòng sử dụng bất cứ trình soạn thảo văn bản nào mà bạn ưa thích cho các tài liệu ấy.


Các phép biến đổi XML

Việc biến đổi XML thường liên quan đến các công nghệ sau đây:

  • XSLT 1.0, chuyển đổi một tài liệu XML thành dạng khác.
  • XPath 1.0,có tìm kiếm và duyệt đi qua một tài liệu XML và cũng tạo điều kiện thuận lợi cho các phép tính toán học và chuỗi ký tự.
  • CSS, định dạng tài liệu XML.

Các tài liệu cá thể XML

Hướng dẫn này sử dụng cùng một tài liệu XML ví dụ về danh mục (catalog) đĩa DVD như trong Phần 3 (xem Tài nguyên). Để thuận tiện, Liệt kê 1 hiển thị lại tài liệu này. Phần lớn các phép biến đổi mà bạn sẽ viết cho hướng dẫn này sẽ hoạt động theo tài liệu này.

Liệt kê 1. Tài liệu cá thể XML cho danh mục đĩa DVD
<?xml version="1.0"?>
<catalog>
    <dvd code="_1234567">
        <title>Terminator 2</title>
   <description>A shape-shifting cyborg is sent back
      from the future to kill the leader of the
             resistance.</description>
        <price>19.95</price>
        <year>1991<year>
    </dvd>
    <dvd code="_7654321">
        <title>The Matrix</title>
        <price>12.95<price>
        <year>1999<year>
    </dvd>
    <dvd code="_2255577" genre="Drama">
        <title>Life as a House</title>
   <description>When a man is diagnosed with terminal
      cancer, he takes custody of his misanthropic
             teenage son.</description>
        <price>15.95</price>
        <year>2001</year>
    </dvd>
    <dvd code="_7755522" genre="Action">
        <title>Raiders of the Lost Ark</title>
        <price>14.95</price>
        <year>1981</year>
    </dvd>   
</catalog>

Một tài liệu cá thể XML khác về một bản đồ trang Web sẽ được hiển thị sau.


XSLT

Điều kỳ diệu là ở chỗ chúng ta có thể nhìn thấy những cây này và không còn ngạc nhiên nữa.
-- Ralph Waldo Emerson

Đôi khi người ta cho rằng, XML không phải là một ngôn ngữ lập trình. Điều này sẽ là hoàn toàn đúng nếu như không phải là nói về XSLT -- mà chính nó cũng là XML -- vì XSLT đã được chứng tỏ là Turing trọn vẹn. Điều này có nghĩa là bạn có thể sử dụng XSLT để thực hiện bất kỳ tập hợp các tính toán mà bạn có thể làm với bất kỳ máy tính hiện đại nào.

XSLT cơ bản là một hệ thống để khai báo rằng điều gì sẽ xảy ra khi bắt gặp các kiểu phần tử nào đó trong một tài liệu XML. XSLT không được biên dịch; thay vào đó, nó -- cùng với một tài liệu đầu vào XML -- được một bộ xử lý bảng định kiểu (stylesheet) giải thích, chẳng hạn như Xalan hoặc Microsoft XML Core Services (MSXML- Các dịch vụ cốt lõi XML của Microsoft). Bạn có thể hình dung cách sử dụng của nó như là một hàm toán học: XSLT( XML ) = output (kết quả đầu ra).

Bởi vì từ stylesheet xuất hiện trong tên XSLT, một số người trong cộng đồng lập trình cho rằng XSLT không có các khả năng nghiêm túc của một ngôn ngữ lập trình -- nghĩa là, nó chỉ là cái gì đó hơi giống Cascading Style Sheets (CSS-bảng định kiểu xếp tầng). Ta chẳng có gì phản đối CSS, nhưng thật thất vọng (tsk-tsk). Mặc dù không xúc tích như hầu hết các ngôn ngữ khác -- chủ yếu bởi vì nó phải đúng ngữ pháp và cú pháp -- XSLT (được kết hợp với XPath, mà ý nghĩa của nó là để tìm kiếm và duyệt đi qua cấu trúc cây XML và để thực hiện các phép tính toán học và xâu ký tự) có thể rất giàu chức năng. Hoàn toàn có khả năng viết mã ngắn gọn đáng ngạc nhiên, như bạn sẽ thấy sau này khi tôi thảo luận về sự đệ quy (recursion).

Trong các phần tiếp theo, bạn sẽ thấy làm thế nào để sử dụng XSLT và XPath để lấy ra dữ liệu từ các tài liệu XML. Trong hầu hết các ví dụ, dữ liệu này cuối cùng sẽ được định dạng như là HTML.

Phép biến đổi bên trong các trình duyệt Web

Mặc dù các ví dụ mã sau đây giả định rằng các phép biến đổi của bạn sẽ xảy ra hoặc trên máy chủ hoặc trong một môi trường như XMLSpy, các phép biến đổi tiếp theo cũng sẽ làm việc được với rất ít hoặc không sửa đổi bên trong phiên bản mới nhất của các trình duyệt có hỗ trợ XSLT, chẳng hạn như Mozilla Firefox và Microsoft Internet Explorer. Các tài liệu XML được xem trên các trình duyệt này yêu cầu một chỉ thị tương tự như dưới đây, mà bạn phải đặt trong phần mào đầu của tài liệu, ngay bên dưới thẻ <?xml version="1.0"?> ở phía trên cùng của tài liệu đầu vào XML. Việc chỉnh sửa thuộc tính href với các giá trị thích hợp có thể là tuyệt đối hay tương đối:

<?xml-stylesheet type="application/xml" href="http://www.ibm/com/xslt/foo.xslt"?>

Phần tử gốc

Phần tử gốc hoặc phần tử mức cao nhất của bất kỳ phép biến đổi XSL nào, lồng bên trong nó là tất cả các node (nút) con khác, là phần tử xsl:stylesheet hoặc xsl:transform. Bạn có thể sử dụng bất kỳ một trong hai phần tử này, vì chúng muốn nói đền cùng một điều. Bạn có thể viết chúng như sau:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

hoặc:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

Sau đó bạn sẽ đóng các thẻ này ở dưới đáy của tài liệu với </xsl:stylesheet hoặc </xsl:transform>, tương ứng. Các thuật ngữ stylesheettransform (biến đổi) vì thế sẽ được sử dụng thay thế cho nhau trong suốt hướng dẫn này.

Các phần tử khuôn mẫu

Phần tử xsl:template có chứa một bộ các quy tắc mà bạn áp dụng để chỉ rõ các phần tử trong một tài liệu đầu vào XML. Mỗi xsl:stylesheet hay xsl:transform phải có ít nhất một phần tử xsl:template. Hầu hết sự phong phú của việc lập trình XSLT xuất phát từ việc sử dụng nhiều khuôn mẫu như là các mô đun logic, mỗi mô đun đều có mục đích riêng của mình. Bạn có thể kích hoạt các phần tử khuôn mẫu thông qua một thuộc tính match hay bằng cách viện dẫn trực tiếp thông qua một thuộc tính name.

XSLT trong XMLSpy®

Trong XMLSpy, bạn có thể biến đổi một tài liệu XML với XSLT:

  1. Nạp tài liệu XML trong XMLSpy.
  2. Nạp tài liệu XSLT trong XMLSpy.
  3. Trong khi tài liệu XML được điểm sáng (in focus), nhấn phím.
  4. Để chọn tài liệu XSLT, nhấn vào nút Window và sau đó nhấn OK.
  5. Nhấn OK lần nữa sao cho các kết quả biến đổi hiển thị.

Việc sử dụng thuộc tính match khá đơn giản. Khi một mẫu được chỉ thị bằng giá trị của thuộc tính match được tìm thấy, một quy tắc được thi hành. Ví dụ, bạn có thể sử dụng mã lệnh sau đây để cho biết mỗi phần tử dvd có trong tài liệu với chuỗi ký tự "Another DVD" (Đĩa DVD khác):

<xsl:template match="dvd">Another DVD</xsl:template>

Kết quả đầu ra của phép biến đổi này trông giống như sau:

<?xml version="1.0" encoding="UTF-8"?>

    <p>Another DVD</p>
    <p>Another DVD</p>
    <p>Another DVD</p>
    <p>Another DVD</p>

Lưu ý rằng có một lần xuất hiện của quy tắc khuôn mẫu cho mỗi phần tử dvd trong tài liệu đầu vào. Mỗi khi phần tử dvd được tìm thấy trong tài liệu đầu vào, quy tắc này được gọi.

xsl:apply-templates và xsl:value-of

Thật có ích khi có các quy tắc khuôn mẫu đáp ứng với các phần tử khác hơn là chỉ một quy tắc cho các phần tử dvd. Thực vậy, bạn có thể có các khuôn mẫu khớp với các phần tử đáng quan tâm khác:

<xsl:template match="price"><xsl:value-of select="."/></xsl:template>
<xsl:template match="title"><xsl:value-of select="."/></xsl:template>

Nút bối cảnh

Nút bối cảnh (context node) là phần tử hiện đang được xem xét. Tất cả các phần tử khác được tham chiếu (thông qua các biểu thức XPath) tương đối so với nút bối cảnh.

Giá trị của thuộc tính select của thẻ <xsl:value-of/> trong cả hai trường hợp là một mẫu đưa ra giá trị văn bản của phần tử hiện tại đang được xem xét hoặc nút bối cảnh. Biểu thức XPath đã biểu thị chính giá trị của thuộc tính select nói trên bằng dấu "." là trục chính nó (self axis). Giá trị của thuộc tính match của thẻ khuôn mẫu (template) cũng là một biểu thức XPath. Ở đây, nút bối cảnh được thiết lập bởi sự ăn khớp với khuôn mẫu. Các cách khác thiết lập nút bối cảnh là sử dụng xsl:apply-templatesxsl:for-each.

Hai thẻ khuôn mẫu trước đó sẽ không cung cấp cho bạn chỉ các giá trị tiêu đề (title) và giá cả (price); mọi thứ khác trong tài liệu đầu vào XML cũng sẽ được hiển thị. Để chỉ hiển thị các giá trị của phần tử titleprice bạn cần nhiều hơn là chỉ một quy tắc khuôn mẫu:

<xsl:template match="dvd">
   <p>
      <xsl:apply-templates select="title"/>- $<xsl:apply-templates select="price"/>
   </p>
</xsl:template>

Một số định dạng HTML nhỏ (một thẻ <p/> ) cũng đã được thêm vào. Kết quả đầu ra trông như sau:

<?xml version="1.0" encoding="UTF-8"?>

    <p>Terminator 2 - $19.95</p>
    <p>The Matrix - $12.95</p>
    <p>Life as a House - $15.95</p>
    <p>Raiders of the Lost Ark - $14.95</p>

Gọi các khuôn mẫu

Một biến thể của cách tiếp cận trước, mở ra các khả năng khác là để dứt khoát gọi các khuôn mẫu để hiển thị các phần tử con titleprice của phần tử dvd. Trong trường hợp này, toàn bộ phép biến đổi trông giống như sau:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="dvd">
      <p>
         <xsl:call-template name="Title"/>
         <xsl:call-template name="Price"/>
      </p>
   </xsl:template>
   <xsl:template name="Title"><xsl:value-of select="title"/> - </xsl:template>
   <xsl:template name="Price">$<xsl:value-of select="price"/></xsl:template>
</xsl:stylesheet>

Để dễ đọc, dấu nối (hyphen) trong tiêu đề và ký hiệu đồng đô la trong mức giá đã được di chuyển vào các khuôn mẫu có tên là Title và Price. Bây giờ, đây là cùng kết quả đầu ra mà phép biến đổi trước đây đã tạo ra:

<?xml version="1.0" encoding="UTF-8"?>

    <p>Terminator 2 - $19.95</p>
    <p>The Matrix - $12.95</p>
    <p>Life as a House - $15.95</p>
    <p>Raiders of the Lost Ark - $14.95</p>

Thuộc tính name của các thẻ xsl:call-template tham chiếu đến các khuôn mẫu mà thuộc tính name của nó có cùng một giá trị: hoặc là "Title" hoặc "Price". Một khuôn mẫu mà bạn gọi nó thông qua thuộc tính name của nó thay vì thông qua một thuộc tính match, được gọi là một khuôn mẫu có tên (named template). Các khuôn mẫu có tên cho phép viết mã theo mô đun. Như bạn sẽ thấy sau này, bạn có thể sử dụng các khuôn mẫu có tên kết hợp với <xsl:import/> hay <xsl:include/>, để cho phép bổ sung thêm các tệp tin bên ngoài -- cho phép các khuôn mẫu được trao đổi vào và ra khi cần thiết. Một cách sử dụng quan trọng khác cho các khuôn mẫu có tên trong XSLT là ở chỗ chúng hỗ trợ việc lập trình đệ quy.

Phép lặp

Tiếp tục với ví dụ tài liệu đầu vào catalog.xml, hãy xem xét các cách để lặp lại một quy tắc khuôn mẫu trên một tập hợp các phần tử. Trong trường hợp này, nút bối cảnh sẽ là phần tử gốc, hay là catalog. Thay cho phương thức đã chỉ ra trước đó phối hợp các phần tử để kích hoạt việc thực thi các quy tắc khuôn mẫu, bạn có thể sử dụng phép lặp với thẻ <xsl:for-each/>.

Trước tiên, hãy xem xét cách làm thế nào để bạn có thể sử dụng xsl:for-each để tạo vòng lặp đi qua từng phần tử dvd trong danh mục:

<xsl:template match="catalog">
   <html>
      <body>
         <xsl:for-each select="dvd">
            <xsl:call-template name="DVD"/>
         <xsl:for-each>
      <body>
   </html>
</xsl:template>

Lưu ý rằng, một số mã HTML đã được bổ sung để định dạng bên trong trình duyệt. Khi xem xét các nội dung của thẻ xsl:for-each, bạn có thể thấy rằng một khuôn mẫu có tên là DVD sẽ được gọi. Khuôn mẫu DVD sau đó có logic hiển thị sau đây:

<xsl:template name="DVD">
   <xsl:variable name="label" select="@code"/>
   <p>
      <img src="images/{$label}.gif" alt=""/>
      <xsl:value-of select="title"/>
   </p>
<xsl:template>

Các biến trong XSLT

Cần nhấn mạnh rằng xsl:variable là không thay đổi được -- có nghĩa là, bạn không thể thay đổi giá trị của nó trong cùng một phạm vi. (Không có phần tử xsl:constant, mặc dù đây có thể là một cái tên thích hợp hơn).

Hầu hết các lập trình viên XSLT mới nhận thấy hành vi này gây phiền nhiễu, nhưng cũng có các lợi ích từ điều này. Có sự nhất trí trong cộng đồng lập trình khi nói về việc này một cách chặt chẽ, XSLT không phải là một ngôn ngữ lập trình hàm (functional programming language) -- tuy nhiên, nó có mang một số nét tương đồng với một ngôn ngữ lập trình hàm. Một trong những đặc điểm mà XSLT chia sẻ với các ngôn ngữ lập trình hàm là nó ngăn chặn các tác động phụ đối với các biến. Điều này cho phép các lập trình viên XSLT biết rằng, khi một khuôn mẫu trả về các giá trị đúng, nó có thể được tin cậy để làm như vậy kể từ đó trở đi bởi vì không một khuôn mẫu nào khác có thể thay đổi các giá trị của bất kỳ "các biến" nào mà khuôn mẫu đang sử dụng.

Tuy nhiên, ngay cả khi các biến không thay đổi trong XSLT, bạn có thể khai báo một biến mỗi khi khuôn mẫu DVD được gọi trong ví dụ, vì mỗi lần được gọi thiết lập một phạm vi khác.

Ví dụ trên đây tiết lộ một số khái niệm mới. Trước tiên, có một xsl:variable tên là nhãn (label). Lưu ý rằng biến này nhận giá trị của thuộc tính code của phần tử dvd, biểu thị bằng tiền tố "@". Cũng lưu ý rằng xsl:for-each di chuyển nút bối cảnh lần lượt tới mỗi phần tử dvd. Bạn có thể thấy điều này trong khuôn mẫu DVD trước đó, bởi vì bạn có thể tham khảo trực tiếp cả thuộc tính @code lẫn giá trị của phần tử title -- cả hai đều là con của phần tử dvd. Các biểu thức Xpath đường dẫn tương đối này phản ánh một thực tế là xsl:for-each di chuyển nút bối cảnh tới mỗi một trong các phần tử dvd.

Thứ hai, biến nhãn (label) mới được sử dụng để tạo ra một thẻ <img/> dành cho việc định dạng HTML mới, trơn tru. (Ở đây giả định có sự hiện diện của một hình ảnh trong thư mục images/ cho mỗi đĩa DVD. Mỗi hình ảnh sau đó sẽ lấy giá trị thuộc tính code của DVD làm tên tệp tin của nó). Lưu ý rằng để có được giá trị của biến, bạn đặt một dấu đồng đô la ("$") ở phía trước nó và sau đó bọc nó bằng các dấu ngoặc cong ("{" và "}"); điều này tương tự như việc sử dụng phần tử xsl:value-of. (Tất nhiên, bạn không cần phải tạo ra biến trong ví dụ này; để thay thế bạn có thể chỉ cần trực tiếp tham khảo giá trị thuộc tính @code bên trong thẻ img như thế này: <img src="images/{@code}.gif" alt=""/>.)

Sắp xếp các đoạn mã lại với nhau trông như sau:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html"/>
   <xsl:template match="catalog">
      <html>
         <body>
            <xsl:for-each select="dvd">
               <xsl:call-template name="DVD"/>
            </xsl:for-each>
         </body>
      </html>
   </xsl:template>
   <xsl:template name="DVD">
      <xsl:variable name="label" select="@code"/>
      <p>
         <img src="images/{$label}.gif" alt=""/>
         <xsl:value-of select="title"/>
      </p>
   <xsl:template>
<xsl:stylesheet>

Như vậy, phép biến đổi trên tạo ra kết quả sau đây:

<html>
<body>
<p>
<img alt="" src="images/_1234567.gif">Terminator 2</p>
<p>
<img alt="" src="images/_7654321.gif">The Matrix</p>
<p>
<img alt="" src="images/_2255577.gif">Life as a House</p>
<p>
<img alt="" src="images/_7755522.gif">Raiders of the Lost Ark</p>
</body>
</html>

Định dạng kết quả đầu ra

Bạn có thể đã nhận thấy rằng kết quả đưa ra trước đây không còn có thẻ <?xml?> ở đầu trang nữa. Điều này là do hai sự việc sau đây -- bất kỳ việc nào trong số hai việc này cũng sẽ làm cho kết quả được xử lý như là HTML. Thứ nhất, thẻ <xsl:output method="html"/> đã được bổ sung thêm ngay sau thẻ mở <xsl:stylesheet>. Thuộc tính phương thức (method) của xsl:output thường nhận hoặc giá trị này (html) hoặc xml. Một thuộc tính có ích khác của thẻ xsl:outputencoding, nó định nghĩa tập hợp ký tự kết quả đầu ra và được sử dụng khi giá trị của thuộc tính method là xml. Một lý do khác là tại sao thẻ <?xml?> bị mất là ở chỗ hầu hết các trình xử lý bảng định kiểu (stylesheet) nhận biết được khi các thẻ HTML được sử dụng, chẳng hạn như <html/><body/>, mà bạn đã bao gồm trong khuôn mẫu đã so khớp. Khi việc này xảy ra, phương thức xuất ra kết quả được tự động xem là dưới dạng HTML.

Sắp xếp các kết quả

Thứ tự tài liệu

Thứ tự tài liệu (Document order) chỉ đơn giản là thứ tự trong đó các phần tử xuất hiện trong một tài liệu XML. Theo lược đồ này, các phần tử cha mẹ xuất hiện trước các phần tử con của chúng; điều này làm cho phần tử gốc là phần tử đầu tiên trong bất kỳ tài liệu nào.

Một phụ kiện có ích cho xsl:for-eachxsl:sort. (Nó cũng làm việc với xsl:apply-templates). Bạn có thể sử dụng thẻ này như là phần tử con đầu tiên của một xsl:for-each để thay đổi thứ tự của các kết quả từ thứ tự tài liệu đến một thứ tự khác, dựa trên một khóa nào đó. Ví dụ, xsl:for-each trong ví dụ trước có thể sử dụng xsl:sort để sắp xếp thứ tự danh sách các đĩa DVD theo giá trị của thuộc tính title của chúng:

<xsl:for-each select="dvd">
   <xsl:sort select="title"/>
   <xsl:call-template name="DVD"/>
</xsl:for-each>

Việc kết hợp văn bản in đậm xsl:sort bên trên vào phép biến đổi trước đây sẽ cho kết quả sau:

<html>
<body>
<p>
<img alt="" src="images/_2255577.gif">Life as a House</p>
<p>
<img alt="" src="images/_7755522.gif">Raiders of the Lost Ark</p>
<p>
<img alt="" src="images/_1234567.gif">Terminator 2</p>
<p>
<img alt="" src="images/_7654321.gif">The Matrix</p>
</body>
</html>

Lưu ý rằng các đĩa DVD hiện nay được sắp xếp tiêu đề theo thứ tự abc. Bạn có thể đặt các phần tử xsl:sort bổ sung thêm sau phần tử đầu tiên để cung cấp các cách sắp xếp chi tiết mịn hơn nữa cho tập hợp các kết quả.

Phép đệ quy

Để triển khai thực hiện phép biến đổi danh sách đĩa DVD trước đây thông qua phép đệ quy có chút gì dường như hơi lạ, đó là vì

  • Giải pháp dùng phép lặp đã trình bày, sử dụng xsl:for-each là trực quan hơn đối với các lập trình viên, những người đã quen thuộc với các ngôn ngữ mệnh lệnh (imperative) như ngôn ngữ lập trình Java™.
  • Tình huống cụ thể này phù hợp với một vòng lặp for đơn giản bởi vì nó chỉ đơn giản yêu cầu phải duyệt đi qua một tập hợp nút (và các nút) anh chị em.

Tuy nhiên, trong trường hợp ở đó các phần tử có thể lồng nhau với số mức lồng chưa biết, phép đệ quy là thích hợp nhất để làm công việc này. Ví dụ, một hệ thống tệp tin -- hoặc là như ta sẽ thấy sau này, các trang chủ đề được lồng nhau trong một điểm Web -- là những ứng cử viên tốt nhất. Vì mục đích so sánh, mã sau đây cho thấy một giải pháp đệ quy của bài toán trên, không sắp xếp kết quả:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html"/>
   <xsl:template match="catalog">
      <html>
         <body>
            <xsl:call-template name="DVD">
               <xsl:with-param name="dvdCount" select="count(dvd)"/>
            </xsl:call-template>
         </body>
      </html>
   </xsl:template>
   <xsl:template name="DVD">
      <xsl:param name="position" select="1"/>
      <xsl:param name="dvdCount"/>
      <xsl:variable name="label" select="dvd[$position]/@code"/>
      <p>
         <img src="images/{$label}.gif" alt=""/>
         <xsl:value-of select="dvd[$position]/title"/>
      </p>
      <xsl:if test="$position < $dvdCount">
         <xsl:call-template name="DVD">
            <xsl:with-param name="position" select="$position+1"/>
            <xsl:with-param name="dvdCount" select="$dvdCount"/>
         </xsl:call-template>
      </xsl:if>
   <xsl:template>
</xsl:stylesheet>

Phép biến đổi này mang lại cùng một kết quả đầu ra giống như là giải pháp lặp:

<html>
<body>
<p>
<img alt="" src="images/_2255577.gif">Life as a House</p>
<p>
<img alt="" src="images/_7755522.gif">Raiders of the Lost Ark</p>
<p>
<img alt="" src="images/_1234567.gif">Terminator 2</p>
<p>
<img alt="" src="images/_7654321.gif">The Matrix</p>
<body>
</html>

Phép đệ quy đuôi

Do cuộc gọi đệ quy đến chính nó xảy ra ở vị trí cuối của khuôn mẫu đĩa DVD trong ví dụ này, kiểu đệ quy này được gọi là phép đệ quy đuôi (tail recursion). Về mặt sử dụng máy tính phép đệ quy đuôi có thể ít đắt đỏ hơn các trường hợp đệ quy khác. Điều này là do một số trình xử lý bảng định kiểu (stylesheet) có khả năng để tối ưu hóa lời gọi đệ quy đuôi bằng cách chuyển đổi nó thành phép lặp.

Ở đây, sự đệ quy bắt đầu trong khuôn mẫu ăn khớp từ điểm trên cùng của phép biến đổi thông qua một cuộc gọi tới khuôn mẫu DVD. Khuôn mẫu DVD sau đó tự gọi nó cho đến khi phần tử dvd đang được xét là phần tử cuối cùng.

Thêm một số sự kiện khác nữa đáng được xem xét trong ví dụ này. Một trong số đó là nút bối cảnh sẽ không bao giờ được di chuyển đến bất kỳ phần tử dvd nào. Điều này là do xsl:call-template không thay đổi nút bối cảnh giống như xsl:for-each đã làm. Do đó, biến được định nghĩa trong khuôn mẫu DVD phải tham khảo phần tử dvd hiện tại với sự giúp đỡ của một phần tử xsl:param, đó là position, nó giữ vị trí của phần tử dvd hiện đang được xem xét. Các tham số có thể chuyển từ một khuôn mẫu tới một khuôn mẫu có tên được gọi thông qua thẻ <xsl:with-param/>. <xsl:with-param> luôn là một phần tử con của thẻ <xsl:call-template/>. Các tham số này được chọn ra trong khuôn mẫu được gọi thông qua thẻ <xsl:param/>, thẻ này luôn luôn phải đứng ngay sau thẻ mở <xsl:template/>.

Bạn có thể nhận thấy rằng xsl:param, position, bên trong khuôn mẫu đĩa DVD, có một giá trị mặc định được chỉ thị bởi thuộc tính select. Vì lý do này, không cần thiết phải sử dụng một xsl:with-param tương ứng trong cuộc gọi đầu tiên tới khuôn mẫu đĩa DVD từ khuôn mẫu phù hợp. Việc sử dụng các giá trị mặc định cho các thẻ xsl:param là một cách làm thực hành tốt; nó có thể giúp ngăn ngừa các hành vi bất ngờ trong các khuôn mẫu được gọi. (Nếu như không cần tương phản với hai tham số, tham số dvdCount cũng cần có một giá trị mặc định).

Cũng cần lưu ý trong xsl:call-template ở phần cuối của khuôn mẫu đĩa DVD là tham số position được tăng dần lên khi nó được chuyển tới cá thể kế tiếp của khuôn mẫu đĩa DVD. Như đã thấy trong thuộc tính test của <xsl:if/>, các giá trị của hai tham số được sử dụng như là cơ sở cho điều kiện dừng đệ quy.

Tham số position cũng được sử dụng trong khuôn mẫu đĩa DVD để cho biết phần tử dvd nào đang được xem xét. Điều này được thực hiện thông qua vị ngữ (predicate) được sử dụng để phân biệt rõ phần tử dvd trong thuộc tính select của cả hai thẻ xsl:variablexsl:value-of. Cả hai biểu thức ấy là các biểu thức XPath, mà bạn sẽ tìm hiểu đầy đủ hơn về sau trong hướng dẫn này. Các vị từ XPath được đánh dấu bằng cặp dấu ngoặc vuông ("[" và "]") và xuất hiện liền ngay sau phần tử mà chúng nhằm phân biệt rõ. Lưu ý rằng trong trường hợp này, tham số position được sử dụng trong vị từ để cho biết vị trí của phần tử dvd hiện đang được xem xét: dvd[$position].

Cách sử dụng phần tử <xsl:if/> là khá đơn giản. Nó có một điều kiện được đánh giá trong thuộc tính test bắt buộc của nó để nhận một kết quả Boolean (đúng hoặc sai). Nếu bạn còn phân vân muốn biết, xin nói là không có thẻ <xsl:else/> hoặc <xsl:elseif/>. Thay vì các thẻ đó, bạn sử dụng <xsl:choose/>, sẽ mô tả sau. Cuối cùng, lưu ý rằng dấu nhỏ hơn trong thuộc tính test của phần tử <xsl:if/> phải kèm dấu thoát XML (&lt;>). Nếu sử dụng dấu nhỏ hơn không có dấu thoát (<) sẽ làm cho trình xử lý bảng định kiểu đưa ra một lỗi ngoại lệ, bởi vì ký tự này cũng như dấu góc đóng hay là dấu lớn hơn (>), được sử dụng để chỉ ra nơi bắt đầu và nơi kết thúc của các phần tử XML.

Phép đệ quy với một bản đồ trang Web

Bây giờ hãy xem xét một ví dụ khi mà phép đệ quy là thích hợp hơn. Tài liệu XML mẫu trong Liệt kê 2 hiển thị một bản đồ trang Web của một điểm Web tưởng tượng. Bạn cần phải xây dựng một phép biến đổi để biểu hiện một bản đồ các trang Web, bắt đầu từ mức cao nhất của các trang và sau đó liệt kê theo đệ quy tất cả các trang con -- và các trang con của các trang con -- với độ sâu bất kỳ. Kết quả của phép biến đổi này sẽ là một tài liệu HTML.

Liệt kê 2. Tài liệu cá thể XML cho một bản đồ trang Web
<?xml version="1.0"?>
<site>
   <page label="A" href="0.html">
      <page label="AA" href="0_0.html">
         <page label="AAA" href="0_0_0.html">
            <page label="AAAA" href="0_0_0_0.html"/>
            <page label="AAAB" href="0_0_0_1.html"/>
            <page label="AAAC" href="0_0_0_2.html"/>
         </page>
         <page label="AAB" href="0_0_1.html"/>
         <page label="AAC" href="0_0_2.html"/>
      </page>
      <page label="AB" href="0_1.html"/>
      <page label="AC" href="0_2.html"/>
   </page>
   <page label="B" href="1.html"/>
   <page label="C" href="2.html"/>
</site>

Bản đồ trang Web mẫu trong Liệt kê 2 có bốn mức độ sâu và đề xuất các trang HTML lồng nhau theo chủ đề. Ba trang mức cao nhất có giá trị thuộc tính nhãn (label) là A, B và C. Trang A có ba trang con (AA, AB và AC) và trang con đầu tiên của nó có ba trang con (AAA, AAB và AAC). Cuối cùng, trang AAA có các trang con (AAAA đến AAAC). Cây này cần phải được biểu hiện dưới dạng HTML.

Để hiển thị bản đồ các trang Web, hãy xây dựng một tập hợp các danh sách không sắp thứ tự, lồng nhau trong mã HTML -- một danh sách cho mỗi mức dẫn hướng. Để xây dựng các danh sách này, hãy lặp từng bước qua một mức dẫn hướng mỗi lần lặp, bắt đầu từ mức đỉnh cao nhất. Nếu bạn thấy thấy rằng một trang có các trang con của nó, hãy thêm danh sách các trang con đó sau trang hiện tại và sau đó tiếp tục bước tiếp theo của phép lặp qua mức dẫn hướng hiện tại. Dưới dạng mã giả (pseudo-code), thuật toán giống như sau:

Build List;

Build List {
   For each page {
      Write page;
      If (page has child pages)
         Build List;
   }
}

Thuật toán này xử lý một cây dẫn hướng với số mức tùy ý, sử dụng khá ít mã lệnh (dù sao cũng là ít đối với XSLT). Việc đòi hỏi ít mã của XSLT minh chứng cho việc nó thích hợp đến mức nào cho loại nhiệm vụ này. Thêm một dấu gạch nối của cú pháp HTML và tiếp theo sau đó là một phép biến đổi khi sử dụng logic trước đây. Các chú thích được bổ sung thêm để nối nó với thuật toán:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="site">
   <html>
      <body>
         <!-- Make the initial template call -->
         <xsl:call-template name="BuildList"/>
      </body>
   </html>
</xsl:template>
<xsl:template name="BuildList">
   <ul>
      <xsl:for-each select="page">
         <!-- Write the current page -->
         <li>
            <a href="{@href}">
               <xsl:value-of select="@label"/>
            </a>
         </li>
         <!-- If the page has child pages, -->
         <xsl:if test="count(page) > 0">
            <!-- Build that list of pages, starting the process again... -->
            <xsl:call-template name="BuildList"/>
         </xsl:if>
      <xsl:for-each>
   </ul>
</xsl:template>
</xsl:stylesheet>

Lưu ý rằng phép biến đổi trước đây là phép đệ quy đuôi. Ngoài ra, nếu trang hiện tại không có các trang con, điều kiện dừng đệ quy được đáp ứng và lời gọi đệ quy đến khuôn mẫu BuildList không được thực hiện. Kết quả đầu ra HTML của phép biến đổi này sẽ trông giống như sau:

<html>
<body>
   <ul>
      <li><a href="0.html">A</a></li>
      <ul>
         <li><a href="0_0.html">AA</a></li>
         <ul>
            <li><a href="0_0_0.html">AAA</a><li>
            <ul>
               <li><a href="0_0_0_0.html">AAAA</a><li>
               <li><a href="0_0_0_1.html">AAAB</a><li>
               <li><a href="0_0_0_2.html">AAAC</a></li>
            </ul>
            <li><a href="0_0_1.html">AAB<a></li>
            <li><a href="0_0_2.html">AAC</a><li>
         <ul>
         <li><a href="0_1.html">AB</a></li>
         <li><a href="0_2.html">AC</a><li>
      </ul>
      <li><a href="1.html">B<a></li>
      <li><a href="2.html">C</a><li>
   <ul>
</body>
</html>

Với các đường liên kết không hoạt động, kết quả đầu ra HTML này biểu hiện trong một trình duyệt giống như sau:

Đệ quy cho một mô đun dẫn hướng trang Web

Bạn có thể làm cho phép biến đổi trước đây trở thành một mô đun dẫn hướng trên cây với việc bổ sung thêm logic để so sánh trang hiện tại (nút bối cảnh) với tất cả các phần tử trang trong bản đồ các trang Web. Điều này là do mỗi trang trong trang Web đòi hỏi một phiên bản mô đun chuyển hướng riêng của nó, dựa vào vị trí của nó trong cây. Bạn cũng cần một số mã JavaScript để kiểm soát việc khai triển ra và thu gọn lại các tập hợp trang anh chị em. Khi đã hoàn tất, mô đun được biểu hiện trông giống các công cụ cây trong Microsoft Windows Explorer và trong khung nhìn Eclipse Navigator.

Khi được biểu hiện lần đầu, các phần tử HTML biểu diễn mọi trang, trừ các trang tầng cao nhất ban đầu, có thuộc tính hiển thị (display) kiểu dáng của chúng được thiết lập là "none" (chi tiết về việc này xem trong CSS dưới đây). Sau đó bạn sử dụng logic mã JavaScript trên trình duyệt để khai triển thẻ HTML biểu diễn từng trang ông bà của nút bối cảnh bằng cách thiết lập giá trị thuộc tính display kiểu dáng thành khối ("block"). Để làm cho hoạt động này là riêng của trang cụ thể, bạn có thể giả định rằng thuộc tính @href của mỗi phần tử trang là duy nhất. Sau đó bạn có thể sử dụng một xsl:variable để giữ giá trị của thuộc tính @href của nút bối cảnh. Thế thì do mỗi phần tử trang tiếp nhận bối cảnh thông qua phép lặp bên trong mỗi tầng dẫn hướng, bạn có thể so sánh thuộc tính @href của nó với xsl:variable đang giữ giá trị @href của trang được biểu hiện. Bằng cách này, các đường liên kết tới trang hiện tại và tất cả các trang ở trên nó được hiển thị.

Nó cũng thích hợp để hiển thị các trang con của trang hiện tại, nếu có. Bạn có thể sử dụng hoặc các phần tử danh sách không sắp thứ tự của HTML như đã thấy trên đây hoặc các thẻ <div/> của HTML để duy trì từng tầng dẫn hướng. Các phần tử này đòi hỏi các giá trị thuộc tính mã nhận dạng id duy nhất để cho bạn có thể bật tắt bằng mã lệnh chương trình các thuộc tính kiểu dáng của chúng giữa display:nonedisplay:block. Nếu bạn sử dụng các thẻ <div/> chúng sẽ cần dùng một giá trị kiểu dáng đệm thêm bên trái khác không hoặc đặt lề trái để mang lại các đoạn thụt vào ở đầu dòng. Việc triển khai thực hiện các gợi ý này được dành cho bạn như là một bài tập. Tuy nhiên, với một vài hình ảnh được thêm vào cho có nét quyến rũ, kết quả phép biến đổi có thể trông giống như một công cụ dẫn hướng dạng cây như được hiển thị trong Hình 1. Hình ảnh là biểu hiện kết quả đầu ra HTML của phép biến đổi XSLT đệ quy, là cơ sở của hầu hết các gợi ý đã cho. Tuy nhiên, thay cho các phần tử lồng nhau tôi cho các phần tử anh chị em với các mối quan hệ trỏ đến cha mẹ được triển khai thực hiện thông qua một cặp thuộc tính. Kết quả đầu ra HTML hiển thị trong Hình 1 đã được biểu hiện trong Internet Explore 6.0.

Hình 1. Biểu hiện của mô đun dẫn hướng
Biểu hiện của mô đun dẫn hướng

Trong HTML đã biểu hiện (chứ không phải là hình ảnh hiển thị trong Hình 1), nhấn vào biểu tượng dấu trừ và dấu cộng như vẽ trong Hình 1 sẽ thu gọn lại và khai triển ra cây con (subtree) bên dưới chúng, còn khi nhấn chuột vào phần văn bản của nút thì sẽ dẫn hướng bạn đến trang đó. (Tất cả các nút trong Hình 1 được hiển thị đã khai triển để lộ ra toàn bộ cây). Sau khi trang đích được nạp vào trong trình duyệt, tất cả các nút ban đầu được thu gọn lại sao cho chỉ có các trang tầng cao nhất được hiển thị. Như vậy, cây được khai triển từ trang hiện tại trở lên trên (hay thực sự là về phía trái) đến tầng trên cùng để cho tất cả các trang ông bà và trang hiện tại được nhìn thấy. Việc khai triển cây đến trang hiện tại cũng để lộ ra bất cứ các trang con nào mà nó có thể có.

Điều kiện dừng

Một gợi ý đệ quy cuối cùng: Giống như phanh trên xe ô tô, điều kiện dừng là sống còn -- vì thế trước tiên cần hiểu và mã hóa nó.

Do bản chất lồng nhau của các tài liệu XML, kết hợp với thực tế là các phần tử xsl:variable là không thể thay đổi được, bạn sẽ thấy là có lợi hơn khi suy nghĩ và mã hóa theo đệ quy để giải quyết hầu hết các bài toán trong XSLT. Nhìn chung, thủ thuật để làm điều này chính là thiết kế các khuôn mẫu của bạn sao cho, giống như khuôn mẫu BuildList, chúng đủ tổng quát để áp dụng cho tất cả các trường hợp của các bài toán sắp tới. Nếu chúng được thiết kế như vậy, thì chúng có thể chỉ cần tự gọi mình khi cần thiết.

Logic điều kiện

Quay trở lại ví dụ danh mục đĩa DVD, giả sử bạn muốn dựa vào một số khía cạnh của một báo cáo về các đĩa DVD trong danh mục theo giá của mỗi đĩa DVD. Thay vì hiển thị mức giá, bạn có thể muốn phân loại đĩa DVD theo giá. Để làm được điều này, bạn sẽ sử dụng xsl:choose.

Ta hãy sửa đổi giải pháp lặp được sử dụng trước đây để hiển thị mỗi phần tử dvd bằng cách gọi khuôn mẫu Price mà bạn đã viết trước đó:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html"/>
   <xsl:template match="catalog">
      <html>
         <body>
            <xsl:for-each select="dvd">
               <xsl:call-template name="DVD"/>
            </xsl:for-each>
         </body>
      </html>
   </xsl:template>
   <xsl:template name="DVD">
      <p>
      <xsl:value-of select="title"/>
         <xsl:call-template name="Price"/>
      </p>
   </xsl:template>
   <xsl:template name="Price">$<xsl:value-of select="price"/><xsl:template>
</xsl:stylesheet>

Bây giờ, hãy sửa đổi khuôn mẫu Price để hiển thị một trong ba tính từ ( "Đắt tiền-Pricey!", "Rẻ tiền-Cheap!," và "Vừa phải - So so") thay cho số Đô la:

<xsl:template name="Price">
   <xsl:choose>
      <xsl:when test="price < 15.00"> - Cheap!</xsl:when>
      <xsl:when test="price > 19.00"> - Pricey!</xsl:when>
      <xsl:otherwise> - So so</xsl:otherwise>
   </xsl:choose>
</xsl:template>

Lưu ý rằng xsl:choose có hai phần tử con: xsl:when, là phần tử con bắt buộc phải có, hành xử giống như xsl:ifxsl:otherwise, là phần tử con tùy chọn. Kết quả đầu ra của phép biến đổi này khi sử dụng xsl:choose trông giống như sau:

<html>
<body>
<p>Terminator 2 - Pricey!</p>
<p>The Matrix - Cheap!</p>
<p>Life as a House - So so<p>
<p>Raiders of the Lost Ark - Cheap!</p>
</body>
</html>

Giống như hầu hết những người viết mã XSLT, bạn sẽ bị giật mình do không có phần tử xsl:else và xsl:else-if nào -- và xsl:choose là dài dòng như vậy. XSLT 2.0 có một giải pháp cho việc này, nhưng tôi sẽ không thảo luận về nó trong hướng dẫn này. XML in a Nutshell, 3rd Edition (xem Tài nguyên) trong hầu hết các chương đều có phần thảo luận về sự khác nhau giữa các phiên bản 1.0 và 2.0 của XSLT và XPath.

Nhập khẩu và bao gồm thêm các khuôn mẫu từ các tệp tin khác

Hai phần tử xsl:importxsl:include cho phép bổ sung thêm các khuôn mẫu từ các tệp tin khác vào phép biến đổi của bạn. Các phần tử này cả hai đều được cho phép chỉ như là phần tử con của phần tử <xsl:stylesheet/> hoặc <xsl:transform/> và cũng phải xuất hiện trước bất kỳ các phần tử mức cao nhất nào khác. Cú pháp cho chúng như sau:

<xsl:import href="URI"/>

<xsl:include href="URI"/>

Giá trị URI của các thuộc tính href nói đến đường dẫn và tên của tệp tin có chứa phép biến đổi đang được thêm vào. Giá trị URI có thể tương đối hoặc tuyệt đối. Sự khác biệt giữa hai phần tử này là các khuôn mẫu được kết hợp thông qua xsl:import được phép có các xung đột tên, trong trường hợp này các khuôn mẫu được nhập khẩu bị bỏ qua. Với xsl:include, các khuôn mẫu có tên thuộc về các phép biến đổi được đưa vào không thể va chạm với bất kỳ khuôn mẫu nào trong phép biến đổi nhập khẩu. Các tệp tin này chỉ đơn giản được sao chép vào phép biến đổi đang xét, tại vị trí của xsl:include. Đối với cả hai phần tử này, không được phép có sự tham khảo vòng tròn giữa các tệp tin nhập khẩu và được nhập khẩu. Như với hầu hết những thứ khác trong XML, việc lồng nhau của các tệp tin thông qua xsl:importxsl:include là được phép.

Tóm tắt XSLT

XSLT là một ngôn ngữ lập trình có nhiều khả năng và ngôn ngữ này cũng có sự mới lạ của tính đúng ngữ pháp và cú pháp. Như bạn sẽ thấy trong phần tiếp theo, XSLT được kết hợp với XPath có thể giải quyết hầu như mọi bài toán tính toán hoặc định dạng bất kỳ. Các thủ thuật để làm chủ XSLT bao gồm việc đạt đến một đánh giá cho các lời gọi khuôn mẫu có tên lồng nhau và trở nên yêu thích phép đệ quy.


XPath

Một hạt táo ẩn ở giữa một quả táo là một vườn táo vô hình.
-- Welsh proverb

Trong phần trước, bạn đã thấy làm thế nào để sử dụng XPath để tham chiếu các phần tử trong các tài liệu XML mẫu. Ví dụ, bạn đã thấy rằng để xem các phần tử trong các cây, các biểu thức XPath như /(gốc tài liệu), page (kiểu phần tử con mong muốn) và .. (hai dấu chấm - phần tử cha mẹ của nút bối cảnh) được sử dụng. Như bạn sẽ thấy trong các phần sau, có thể truy cập vào bất kỳ phần nào của một tài liệu XML thông qua việc kết hợp đúng đắn các biểu thức XPath.

XPath cũng sở hữu các hàm toán học, chuỗi ký tự và tập hợp. Mặc dù những thứ này không nhất thiết phải tương đương với hầu hết các ngôn ngữ kịch bản lệnh khác như Perl hay JavaScript về sự ngắn gọn hay sức mạnh, trong hầu hết các trường hợp bạn có thể xây dựng các khuôn mẫu XSLT sao cho các hàm ấy -- được kết hợp với logic thích hợp -- có thể hoàn thành bất cứ điều gì mà bạn có thể làm trong các ngôn ngữ khác. Phần này dành để làm rõ các biểu thức XPath ta đã thấy trong phần trước về XSLT và để phát triển rõ thêm một số khái niệm.

Các trục

Một khái niệm then chốt trong XPath là khái niệm về các trục (axes). Một trục trong XPath là một tập hợp các nút (node) nằm ở bên trên (như các phần tử cha mẹ tổ tiên, ở bên dưới (các phần tử conhậu duệ, ở phía bên trái (các phần tử anh chi em đứng trướcđứng trước nữa, hay ở bên phải (các phần tử anh chị em tiếp theotiếp sau nữa) của nút bối cảnh. Các trục đứng trướctiếp sau nói đến các phần tử xuất hiện trước và sau nút bối cảnh, một cách tương ứng, theo thứ tự tài liệu, trong khi đó trục các anh chị đứng trướccác em đứng sau nói đến các phần tử có cùng một phần tử cha mẹ như là nút bối cảnh. Trục self (chính bản thân) là nói về chính nút bối cảnh và có thể được kết hợp với hai trục khác để tạo thành các trục tổ tiên hoặc bản thânhậu thế hoặc bản thân. Sau đó, truy cập vào bất kỳ phần nào của một tài liệu XML được bảo đảm bằng cách bổ sung thêm vào các trục nói trên các trục thuộc tính (attribute) và không gian tên (namespace).

Các cú pháp được viết tắt và không được viết tắt

Một số các trục XPath có thể, nhưng không nhất thiết, được biểu diễn theo một cú pháp viết tắt có một cái gì tương đồng với cú pháp shell của hệ thống tệp tin của UNIX® Đó là, các phần tử con (được chỉ thị bằng dấu hoa thị (*) hoặc tường minh hơn với kiểu phần tử con mong muốn), phần tử cha mẹ (..), chính nó (.), thuộc tính (@") và các trục hậu thế hoặc bản thân (//). Các trục khác phải sử dụng một cú pháp không viết tắt. Bạn sẽ thấy cú pháp này trong một số ví dụ tiếp sau.

Các bước vị trí và đường dẫn vị trí

Các bước vị trí tạo thành cơ sở của một đường dẫn vị trí. Dấu phân cách cho một bước vị trí là dấu vạch chéo thuận (/). Một đường dẫn vị trí là một loạt các cá thể móc nối vào nhau của các trục đã nói trên đây. Ví dụ, bắt đầu từ một nút bối cảnh, một đường dẫn vị trí có thể tiến lên hai mức, tìm một phần tử được chỉ rõ bởi một vị từ, nhìn xuống dưới tìm bên trong cây con này một phần tử cụ thể và trả về một trong các thuộc tính của nó:

../../page[starts-with(@label, 'A')]//page[count(ancestor::page) = 3]/@href

Các hàm XPath

Trích lấy các giá trị trong XPath

Lưu ý rằng một dấu nháy đơn (') được sử dụng trong biểu thức XPath ở trên. Đấy là do biểu thức này sẽ có nhiều khả năng xuất hiện bên trong một thẻ XSLT nào đó, như là giá trị của một thuộc tính nào đó. Giá trị thuộc tính tất nhiên sẽ được bao bọc trong cặp dấu nháy kép ("), do đó việc sử dụng các dấu nháy kép trong những thứ nhúng bên trong, chẳng hạn như là một biểu thức XPath, sẽ phá vỡ cú pháp thẻ XSLT.

Bạn có thể hoàn thành các phép toán chuỗi ký tự và phép toán số học trong XSLT thông qua các hàm được XPath cung cấp. Ví dụ, nếu bạn cần phải thêm các giá trị của hai phần tử xsl:variable x và y, bạn sẽ sử dụng:

<xsl:value-of select="$x + $y"/>

Phép toán này trả về một số, giống như nhiều hàm XPath khác. XPath cung cấp các hàm cho các phép tính toán sau đây: Cộng (+), trừ (-), nhân (*), chia (div) và chia mô đun (modulo) hay lấy số dư (mod).

Các hàm XPath cũng có thể trả về một giá trị kiểu Boolean (đúng hoặc sai). Điều này là quan trọng đối với logic điều kiện:

<xsl:if test="$x > $y"> ... </xsl:if>

Các hàm XPath cũng có thể trả về các chuỗi ký tự:

<xsl:value-of select="concat($x, ' - ', $y)"/>

Trong trường hợp này, hàm concat() có thể nhận một số lượng bất kỳ lớn hơn một các đối số. Một hàm chuỗi ký tự có ích khác là normalize-space(string), nó tước bỏ khoảng trống thừa ở đuôi và thu gọn tất cả các chuỗi ký tự khoảng trống nằm bên trong xuống chỉ còn một khoảng trống. Danh sách sau đây bao gồm các hàm XPath khác có liên quan đến chuỗi ký tự:

  • starts-with(string, string): Trả về true khi đối số đầu tiên có chứa chuỗi ký tự bắt đầu là đối số thứ hai; nếu không, nó trả về false.
  • contains(string, string): Trả về true khi đối số đầu tiên có chứa chuỗi ký tự là đối số thứ hai; nếu không, nó trả về false.
  • substring-before(string, string): Trả về phần chuỗi con của đối số đầu tiên xuất hiện trước đối số thứ hai.
  • substring-after(string, string): Trả về phần chuỗi con của đối số đầu tiên xuất hiện sau đối số thứ hai.
  • substring(string, number, number?): Trả về phần chuỗi con của đối số đầu tiên bắt đầu từ vị trí được chỉ ra bởi đối số thứ hai và có một độ dài được chỉ ra bởi đối số thứ ba. Lưu ý rằng các vị trí trong hàm này tính bắt đầu từ 1, không phải từ 0.
  • string-length(string?): Trả về một số chỉ ra độ dài của đối số, nếu có đối số. Nếu không có đối số được truyền cho hàm, giá trị của nút bối cảnh được sử dụng.
  • translate(string, string, string): Trả về chuỗi ký tự là đối số đầu tiên sau khi thay thế tương ứng các ký tự có xuất hiện trong đối số thứ hai bằng các ký tự tương ứng theo vị trí ở trong đối số thứ ba.

Các hàm XPath cũng có thể trả về các tập hợp nút. Ví dụ, trong ví dụ sitemap.xml, bạn có thể tìm thấy một số phần tử trang có các phần tử của trang con:

<xsl:value-of select="count(//page[page])"/>

Ở đây, một kết quả là tập hợp nút được bao bọc bằng một hàm mà trả về một số. Hàm count() của XPath trả về số 3; nó tính các phần tử trang có các giá trị nhãn A, AA và AAA, mỗi phần tử này có các phần tử trang con. Lưu ý rằng mã lệnh trước đây sử dụng trục hậu thế (descendant) dưới dạng cú pháp viết tắt (//). Khi sử dụng // không có gì đặt trước nó, một phép tìm kiếm đệ quy được thực hiện từ phần tử gốc; các phép tìm kiếm như vậy có thể chi phí rất đắt trong một tài liệu lớn, do đó, hãy thận trọng khi sử dụng. Bên trong dấu ngoặc vuông ([ và ]) là một vị từ (predicate) áp dụng cho các phần tử trang này, yêu cầu rằng chúng phải có các phần tử trang con. Nội dung của vị từ này chính là một biểu thức XPath, "page" bên trong trục con (child). Cũng lưu ý rằng bạn có thể mở rộng logic này cho biểu thức sau đây để nhận được số lượng các trang có các trang con -- mà nó cũng có các trang con -- bằng cách lồng một vị từ khác:

<xsl:value-of select="count(//page[page[page]])"/>

Kết quả, như bạn có thể mong đợi, là 2 -- là tổng số đếm được của các phần tử trang A và AA.

Giả sử rằng bạn muốn tìm xem một nút bối cảnh có độ sâu như thế nào trong cây XML của nó (tầng dẫn hướng, nếu sử dụng ngôn ngữ của ví dụ bản đồ các trang Web). Bạn có thể sử dụng hàm count() một lần nữa, nhưng lúc này dọc theo một trục khác:

<xsl:value-of select="count(ancestor::page)"/>

Các trục tổ tiên được sử dụng để xác định chiều sâu của nút bối cảnh. Cách sử dụng nó được hiển thị ở đây trong một khuôn mẫu:

<xsl:template match="/">
   <xsl:for-each select="//page">
     Page: <xsl:value-of select="@label"/> 
    ,level: <xsl:value-of select="count(ancestor::page)"/>
   </xsl:for-each>
</xsl:template>

Lưu ý rằng xsl:for-each được điều khiển bởi kết quả là tập hợp nút do thuộc tính select cung cấp. Dưới đây là các kết quả đầu ra:

<?xml version="1.0" encoding="UTF-8"?>

         Page: A, level: 0
         Page: AA, level: 1
         Page: AAA, level: 2
         Page: AAAA, level: 3
         Page: AAAB, level: 3
         Page: AAAC, level: 3
         Page: AAB, level: 2
         Page: AAC, level: 2
         Page: AB, level: 1
         Page: AC, level: 1
         Page: B, level: 0
         Page: C, level: 0

Thuộc tính select="//page" trả về một tập hợp nút có chứa tất cả các phần tử trang theo thứ tự trong tài liệu, bắt đầu từ phần tử gốc. Sau đó xsl:for-each thiết lập nút bối cảnh lần lượt tại mỗi một trong các phần tử trang này. Nếu xsl:for-each không có khả năng thiết lập nút bối cảnh, các biểu thức trong các phần tử xsl:value-of sẽ không hoạt động.

Tóm tắt XPath

XPath là quyết định đối với XSLT. Nó là cách thức mà các phép tính toán học và các phép tính chuỗi ký tự sẽ được thực hiện và là cách thức tìm kiếm và duyệt đi qua XML đầu vào. Không có Xpath, XSLT sẽ trở thành mù lòa và móm răng.


CSS

Một người khờ dại không nhìn thấy cùng một cái cây giống như một người khôn ngoan.
-- William Blake

Quy tắc, quy tắc và nhiều quy tắc hơn nữa

XML vốn tự thân là tùy thuộc ngữ cảnh. Tức là, các thẻ của nó, thứ tự của chúng và các cách thức theo đó chúng được lồng nhau nói cho bạn biết nhiều về ý nghĩa của tài liệu. Tuy nhiên, khác với cách sắp xếp của chúng, không có thông tin nào cho biết nội dung XML sẽ được định dạng trực quan như thế nào (hoặc biểu hiện thế nào trong một phương tiện khác). Khung nhìn mặc định của một tài liệu XML trong một trình soạn thảo văn bản hoặc trình duyệt là thấy tất cả các thẻ của nó, không có một cách xử lý trực quan cụ thể nào được áp dụng với một phần tử bất kỳ nào, ngay cả phần tử gốc. Nhưng điều gì sẽ xảy ra khi bạn muốn hiển thị một phông chữ lớn và béo cho các phần tử nhất định nào đó hoặc để hiển thị các phần tử khác trong một danh sách gồm các dòng bắt đầu với dấu chấm tròn hoặc một danh sách có đánh số thứ tự? Điều gì sẽ xảy ra khi cần phải luôn luôn định vị một tập hợp các thông tin tại chính một vị trí trên một trang, hoặc để làm cho màu nền của nhóm đó khác với màu nền của phần tử cha mẹ của nó? Để làm được điều này, bạn có thể ánh xạ các quy tắc trình bày tới các phần tử thông qua CSS.

Các quy tắc trình bày CSS cho phép bạn phân tách thông tin (các phần tử XML) khỏi cách trình bày nó -- sao cho, nếu như bạn muốn, bạn có thể áp dụng bất kỳ một trong nhiều cách nhìn khác nhau về một tập hợp dữ liệu trong các điều kiện khác nhau. Xin lưu ý rằng CSS không thể so sánh được với sức mạnh của XSLT về tạo kiểu dáng hay biến đổi XML; nó cũng không được diễn giải giống nhau trên các nền tảng hoặc các trình duyệt Web khác nhau -- đặc biệt là trong việc hỗ trợ tạo kiểu dáng XML, như bạn sẽ thấy. Tuy nhiên CSS được thảo luận tại đây do đôi khi chỉ cần một cách tiếp cận gọn nhẹ, đó là tất cả những gì cần thiết để thực hiện công việc. CSS là dựa trên cú pháp không XML, khá đơn giản và hoàn toàn dễ sử dụng. Trong hướng dẫn này, các tài liệu CSS sẽ được gọi đơn giản là "các bảng định kiểu".

XML trong các trình duyệt

Mở một tài liệu XML bằng Internet Explore và bạn sẽ nhìn thấy gần tương tự như Hình 2.

Hình 2. Tài liệu XML trong trình duyệt Internet Explorer 6.0
Tài liệu XML trong trình duyệt Internet Explorer 6.0

Khi bạn nhấn vào biểu tượng cộng và trừ, bạn thu hẹp lại và khai triển ra các phần tử là cha mẹ của các phần tử khác -- rất thuần thục -- nhưng với một dáng vẻ ngoài mà chỉ có một sinh viên chuyên ngành khoa học-máy tính có thể ưa thích. Firefox không tốt hơn, nhưng ít nhất nó đưa ra một lời xin lỗi, như Hình 3 chỉ ra.

Hình 3. Tài liệu XML trong trình duyệt Firefox
Tài liệu XML trong trình duyệt Firefox

Thông báo ở bên trên cây trong Firefox ngụ ý rằng giá như đã có thông tin kiểu dáng được kết hợp với tài liệu XML, thì bạn có thể thích nó hơn. Vâng, tốt lắm. Bạn làm điều này như thế nào?

Trong tài liệu HTML, bạn có thể bao gồm thêm các thông tin kiểu dáng theo các hình thức sau đây:

  • Bên trong các thẻ HTML có sử dụng nó -- hay còn gọi là nội tuyến (inline) theo cách nói CSS.
  • Bên trong một thẻ <style/> cho các kiểu dáng bên trong cho tài liệu HTML.
  • Bên ngoài trong một tệp tin khác và được tham khảo thông qua một thẻ <link/> HTML.

Đây là tin tức mà bạn có thể sử dụng nếu bạn viết các phép biến đổi XSL để tạo ra HTML từ XML. Ở đây, tuy nhiên, bạn chỉ cần quan tâm đến việc truyền cho XML một số định dạng trực quan. Nhưng vấn đề là XML có lẽ sẽ không hợp lệ nếu bạn thêm các thuộc tính kiểu dáng nội tuyến vào các phần tử bất cứ ở đâu bạn muốn. Ngoài ra, DTD hoặc lược đồ XML của tài liệu XML nhiều khả năng không bao gồm thêm một phần tử kịch bản lệnh (script), do đó phương thức từ bên trong để áp dụng kiểu dáng cũng sẽ không thực hiện được. Bên cạnh đó, cả hai cách tiếp cận này đều làm thay đổi XML, điều mà bạn không muốn làm. Còn lại cách tiếp cận duy nhất là sử dụng các tệp kiểu dáng bên ngoài -- thông qua một hoặc nhiều tệp tin với tên có đuôi .css -- để áp dụng các cách xử lý trực quan cho các tài liệu XML. Tuy nhiên, bạn không thể sử dụng thẻ <link/> HTML (trừ phi lược đồ XML hay DTD của bạn cho phép nó). Vì vậy, bạn có thể kết hợp một hoặc nhiều tệp tin CSS với một tài liệu XML thông qua một chỉ thị cho trình duyệt tương tự như sau:

<?xml-stylesheet type="text/css" href="catalog.css"?>

Đặt mã lệnh này ở phần bắt đầu của tài liệu XML của bạn, ngay sau chỉ thị <?xml version="1.0"?>. Chỉ thị bảng định kiểu tham khảo một tệp tin CSS, đó là catalog.css, nó ở trong cùng một thư mục như các tệp tin XML. Giá trị của thuộc tính href cũng có thể là đường dẫn tuyệt đối. Bạn có thể sử dụng các thuộc tính khác trong chỉ thị trước đó, một trong số các thuộc tính đó là phương tiện (media). Các giá trị có thể có cho thuộc tính phương tiện bao gồm all , braille (chữ nổi braille), embossed (được rập nổi), handheld (thiết bị cầm tay), print (in ấn), projection (trình chiếu), screen (màn hình), speech (tiếng nói), tty, và tv.

Vì vậy, bạn có thể tham khảo các quy tắc bảng định kiểu xếp tầng (CSS) khác nhau của cùng một tài liệu XML. Điều này cho phép XML được định dạng dành cho phương tiện trong đó nó đang được xem (hoặc nghe!). Bạn có thể thử nghiệm cho phương tiện hiện tại (và như vậy phục vụ nó với cùng một bảng định kiểu) thông qua quy tắc @media. Mã sau đây đưa ra một ví dụ:

@media print {
  body { font-size: 10pt; }
}
@media screen {
  body { font-size: x-small; }
}

Cú pháp

Ngữ pháp cơ sở cho việc định nghĩa một kiểu dáng trong một bảng định kiểu xếp tầng là: selector {property: value;}. Bộ chọn (selector) là phần tử XML mà bạn định nghĩa một dáng vẻ trình bày của nó dựa vào giá trị (value) của một hoặc nhiều thuộc tính (properties). Bạn có thể gộp nhóm nhiều bộ chọn với nhau, tách biệt chúng bằng một dấu phẩy.

Bạn cũng có thể sử dụng bộ chọn đa năng (universal selector), được biểu diễn bằng một dấu hoa thị (*); bộ chọn này có thể áp dụng được cho tất cả mọi thứ trong tài liệu XML mà không định nghĩa một quy tắc rõ ràng. Giá trị thuộc tính được diễn đạt bằng một trong một tập hợp của các đơn vị được cho phép. Các đơn vị này biểu diễn màu sắc, chiều dài v.v, tùy trường hợp. Thông thường, khoảng trống không quan trọng với CSS, cho phép bạn định dạng các tệp tin này theo bất cứ cách nào có ý nghĩa. Tuy nhiên giá trị của một thuộc tính và các đơn vị đo (units) được tính theo nó phải liền nhau, không được tách rời bằng khoảng trống.

Trong CSS, bạn có một số khả năng linh hoạt để định nghĩa các định tố chọn như thế nào. Ví dụ, nếu bạn muốn thiết lập các quy tắc định kiểu cho một tiêu đề phần tử là phần tử con của một phần tử dvd bạn có thể sử dụng quy tắc như sau:

dvd title {font-weight: bold;}

Ở đây, khai báo rằng các giá trị văn bản của của phần tử title của DVD sẽ biểu hiện bằng chữ in đậm. Bạn không buộc phải sử dụng cú pháp này (đơn giản hơn, bạn có thể khai báo ngay title làm bộ chọn), nhưng ghi nhớ quy tắc này sẽ có ích trong trường hợp bạn cần phải định kiểu lại một phần tử xuất hiện trong các bối cảnh khác nhau (có nghĩa là, một phần tử xuất hiện như là phần tử con của một phần tử ở đây, nhưng cũng có thể xuất hiện như là phần tử con của một phần tử khác ở đâu đó). Hình 4 cho thấy tác dụng của việc định kiểu này trong Internet Explore 6.0.

Hình 4. Giới thiệu đầu tiên CSS cho XML
Giới thiệu đầu tiên CSS cho XML

Để dễ đọc, ta hãy giả sử rằng mỗi phần tử dvd được hiển thị thành một đoạn riêng biệt của mình, với một ít ký tự đệm thêm (padding) xung quanh nó:

dvd {
   display: block;
   padding: 5px;
}

Tôi sẽ thảo luận ngắn gọn về các thuộc tính này và giá trị của chúng ngay dưới đây. Bây giờ, nếu bạn muốn làm nổi bật các phần tử dvd bao gồm một thuộc tính thể loại (genre), bạn khai báo quy tắc sau đây:

dvd[genre] {color: blue;}

Các độc giả tinh khôn sẽ nhận ra sự tương đồng may mắn về cú pháp này với các vị từ XPath. Trong khi Internet Explore 6.0 không thừa nhận cú pháp này, thì trình duyệt Firefox 1.0.7 cho kết quả đầu ra được biểu hiện như thấy trong Hình 5.

Hình 5. Các vị ngữ thuộc tính trong trình duyệt Firefox
Các vị ngữ thuộc tính trong trình duyệt Firefox

Bây giờ, hội viên yêu thích của chúng ta, người sưu tầm phim ảnh muốn làm nổi bật các phim thuộc thể loại bi kịch bằng màu sắc ưa thích của mình:

dvd[genre="Drama"] {color: purple;}

Quy tắc này, cùng với một quy tắc tổng quát hơn về việc hiển thị các phần tử dvd có kèm thuộc tính genre, cả hai đều được tuân theo, như thấy trong Hình 6. Một lần nữa, điều này thực hiện được trong Firefox chứ không thực hiện được trong Internet Explore 6.0..

Hình 6. Thêm nhiều vị ngữ thuộc tính nữa trong trình duyệt Firefox
Thêm nhiều vị ngữ thuộc tính nữa trong trình duyệt Firefox

Trông đã khá hơn, nhưng giá cả của mỗi đĩa DVD còn khó đọc một chút có phải không? Hãy đặt một dấu hiệu đồng đô la ở phía trước của mỗi giá trị của phần tử price (giá cả):

price:before {content: "$";}

Ta hãy kèm thêm năm sản xuất bộ phim trong dấu ngoặc đơn. Để thực hiện điều này, bạn có thể sử dụng cùng một kỹ thuật phần tử giả (pseudo element) được sử dụng cho phần tử price:

year:before {content: "  (";}
year:after {content: ")";}

Hình 7 chỉ ra các quy tắc trên đây được biểu hiện trong Firefox.

Hình 7. Biểu hiện phần tử giả
Biểu hiện phần tử giả

Internet Explore 6.0 không thừa nhận các phần tử giả selector:beforeselector:after do đó, kết quả biểu hiện không được hiển thị

Hãy thêm vào một số định dạng nữa cho những gì mà chúng ta đã làm:

Liệt kê 3. Bảng định kiểu để định dạng trực quan tài liệu XML về bộ sưu tập đĩa DVD
/*
**  catalog.css
**  This stylesheet visually formats our DVD collection XML doc.
*/

catalog {
   font-family: Verdana, Arial, Helvetica, Sans-serif;
   font-size: x-small;
   padding: 25px;
   background-color: #DDDDCC;
}

dvd {
   display: block;
   padding-bottom: 8px;
   border-top:     1px solid gray;
   border-left:    2px solid #666666;
   border-right:   2px solid white;
   border-bottom:  1px solid white;
   background-color: #E8E8FF;
}

dvd:first-child {
   border-top:     2px solid #666666;
}

dvd:last-child {
   border-bottom:  2px solid white;
}

dvd title {
   display: block;
   font-weight: bold;
}

dvd[genre] {
   color: blue;
}

dvd[genre="Drama"] {
   color: purple;
}

dvd[genre="Action"] {
   display: none;
}

price:before {content: "$";}

year:before {content: "  (";}
year:after {content: ")";}

Ở đây, bạn đã thêm vào một số các thuộc tính vào phần tử danh mục (catalog) (là phần tử gốc) để định nghĩa toàn bộ tài liệu. Điều này thiết lập các quy tắc tổng thể cho màu nền, đường viền, họ phông chữ (font-family) và cỡ phông chữ (font-size). Như bạn sẽ thấy trong kết quả biểu hiện đầu ra, các thuộc tính phông chữ này được tất cả các phần tử con của phần tử catalogthừa kế. Do catalog là phần tử gốc, các quy tắc này áp dụng cho toàn bộ tài liệu. Các phần tử được lồng bên trong có thể có các quy tắc của thuộc tính phông chữ riêng của nó, thuộc tính riêng đó ghi đè lên các thuộc tính kế thừa từ phần tử cha mẹ.

Tiếp theo, bạn đã thêm một số quy tắc tới các phần tử dvd để làm cho chúng nổi bật trên nền (phần tử catalog). Bạn đã sử dụng hai cách khác nhau để mô tả các màu sắc: tên màu và mã số màu theo hệ đếm mười sáu (hexadecimal) -- Tôi sẽ trình bày ngắn gọn những điều này và các cách khác để mô tả màu sắc trong CSS ở phần sau. Bạn đã sử dụng thuộc tính display với một giá trị khối ("block") dành cho các phần tử catalogdvd để làm cho chúng hiển thị trên các dòng riêng biệt của mình và thực hiện phần đệm (padding). Bạn cũng đã thí nghiệm với các bộ chọn lớp giả (pseudo class) của phần tử con đầu tiênphần tử con cuối cùng để cung cấp cho các phần tử dvd đầu tiên và cuối cùng một đường viền (border) có độ dày lớn hơn thường lệ. (Các bộ chọn lớp giả phối hợp các điều kiện của các phần tử thay vì các tên của phần tử). Cuối cùng, hội viên yêu thích của chúng ta, người sưu tầm phim yêu cầu rằng bạn che dấu tất cả các phim thuộc thể loại hành động; điều này được thực hiện bằng cặp thuộc tính và giá trị display: hidden. Hình 8 and Hình 9 cho thấy trình duyệt Firefox và Internet Explore 6.0, tương ứng, xử lý bảng định kiểu này như thế nào.

Hình 8. Bảng định kiểu được biểu hiện trong Firefox
Bảng định kiểu được biểu hiện trong Firefox
Hình 9. Bảng định kiểu được biểu hiện trong Internet Explorer 6.0
Bảng định kiểu được biểu hiện trong Internet Explorer 6.0

Lưu ý rằng trong trình duyệt Firefox, bạn đã thành công trong việc ẩn dấu các DVD có giá trị thuộc tính thể loại (genre) là Hành động (Action) (Raiders of the Lost Ark - Indiana Jones và chiếc rương thánh tích) bằng cách thiết lập thuộc tính display của nó thành "none". Trong thực tế, trình duyệt Firefox thực hiện rất tốt tất cả các quy tắc trong bảng định kiểu. Tuy nhiên, với Internet Explore 6.0 bạn không thành công với nhiều quy tắc. Điều này đặc biệt đúng sau khi bạn đã áp dụng một thuộc tính màu nền (background-color) cho phần tử catalog đây là đốm tròn màu xám bao trùm hầu hết nội dung trong Hình 9. Như được chỉ ra ở đây, Internet Explore 6.0, một trình duyệt không tuân thủ các tiêu chuẩn cho lắm, không so được với trình duyệt Firefox về mặt hỗ trợ CSS cho XML.

Cuối cùng, như nhìn thấy ở phía trên cùng của bảng định kiểu trước đây (Liệt kê 3), bạn có thể sử dụng các chú thích trong các tệp tin CSS. Các chú thích phải bắt đầu bằng /* và kết thúc bằng */, giống như những chú thích được sử dụng trong lập trình C và Java.

Màu sắc

Màu trong CSS điển hình là một bộ ba màu đỏ, xanh lá cây và xanh dương được biểu diễn theo chính thứ tự này và bằng một trong ba cách khác nhau:

  • Số hệ đếm mười sáu (Hexadecimal): Phương pháp này sử dụng các ký số hệ đếm mười sáu từ 0 đến F và F tương đương với số thập phân 15. Ký pháp biểu diễn một màu dưới dạng một số hệ đếm mười sáu bắt đầu với một dấu thăng (#) và tiếp theo sau là các thành phần đứng liền nhau, mỗi phần gồm hai ký số, cho màu đỏ, màu xanh lá cây và màu xanh dương. Ví dụ, # FF0000 chỉ thị màu đỏ tươi, # 000000 chỉ thị màu đen và # 336699 chỉ thị một màu ngọc lam tối.
  • Số thập phân (Decimal): Phương pháp này sử dụng các số nguyên thập phân từ 0 đến 255 trong một ký pháp ba màu đỏ, màu xanh lá cây và xanh dương, được sử dụng như sau: rgb(rr,gg,bb). Ví dụ, rgb(255,0,0) chỉ thị màu đỏ tươi.
  • Phần trăm (Percent): Phương pháp này cũng tương tự như phương pháp số thập phân, nhưng nó sử dụng các tỷ lệ phần trăm từ 0 đến 100 của mỗi thành phần màu sắc. Ví dụ, rgb(100%,0%,0%) chỉ thị màu đỏ tươi.

Bạn cũng có thể biểu diễn các màu sắc bằng cách sử dụng tên màu sắc. Các ví dụ bao gồm red, white, blue và v.v.

Hiển thị

Như thấy trong Liệt kê 3, Thuộc tính hiển thị (display) cho phép bạn hiển thị ra một phần tử theo nhiều cách khác nhau, với các giá trị sau đây:

  • block: (khối): Giá trị này làm cho định tố chọn xuất hiện trong một vùng hình chữ nhật. Một dấu ngắt dòng xuất hiện trước và sau nội dung này.
  • inline: (nội dòng): Giá trị này làm cho đoạn văn bản là giá trị của phần tử xuất hiện trên cùng một dòng như là các phần tử lân cận, không có dấu ngắt dòng nào ở đầu hay cuối dòng. Tuy nhiên, có thể có các dấu ngắt dòng bên trong nếu các nội dung đủ dài. Đây là hành vi hiển thị mặc định.
  • none: (không có gì): Giá trị này không chỉ buộc các phần tử nội dung biến mất, mà cả vùng không gian cấp cho nó cũng được gỡ bỏ; điều này có vẻ trái ngược với thuộc tính visibility: hidden và giá trị bị ẩn dấu, trong khi khoảng không gian đã gán vẫn còn.
  • list: (danh sách): Các phần tử được hiển thị theo cách này được sử dụng để tạo thành một danh sách có số thứ tự hay không có số thứ tự.

Các phần tử bảng (Table) đưa ra một vài sự hỗ trợ các lựa chọn CSS thay thế cho các bảng HTML; chúng có thể bắt buộc các phần tử hoạt động giống như các phần tử table, trtd trong HTML, nếu lồng nhau đúng. Tuy nhiên, hãy quên nó đi khi bạn cần có chức năng tương đương chính xác với giãn cách dòng (rowspan) hay giãn cách cột (colspan); của bảng HTML; trong các trường hợp này không có phần tử có định kiểu lồng nhau nào sẽ đáp ứng được.

Độ dài

Các độ dài được sử dụng cho nhiều thuộc tính CSS. Tất cả chiều rộng, chiều cao, cỡ phông chữ, đường viền, phần đệm thêm, khoảng cách lề và việc xác định vị trí, tất cả đều sử dụng một số đơn vị độ dài để mô tả các giá trị của chúng. Các độ dài hoặc là tuyệt đối hoặc là tương đối. Các đơn vị tuyệt đối là thích hợp đối với phương tiện in ấn (nhưng không thích hợp cho nhiều phương tiện khác), bao gồm các điểm, picas, millimet, centimet và inch. Đơn vị tương đối thường được sử dụng cho phương tiện màn hình, bao gồm các điểm ảnh, tỷ lệ phần trăm, ems và exes.

Thoạt đầu, các điểm ảnh (Pixel) có thể có vẻ giống như các đơn vị tuyệt đối nhưng chúng là tương đối so với độ phân giải của thiết bị hiển thị. Các điểm ảnh thường được sử dụng để điều chỉnh các phần tử kiểu khối tương ứng với các hình ảnh bitmap, nhưng tránh sử dụng chúng làm cỡ chữ. Khi đơn vị điểm ảnh (pixel) được sử dụng để mô tả một cỡ chữ, nó được xử lý như là một đơn vị tuyệt đối và hầu hết các trình duyệt không cho phép những người sử dụng co giãn cỡ chữ mà nó mô tả cho dễ đọc.

Tỷ lệ phần trăm mô tả độ dài của một cái gì đó tương đối so với một đối tượng khác nào đó. Thông thường, đối tượng này là khoảng trống lớn nhất có sẵn. Như vậy, một thuộc tính chiều rộng với một giá trị 60% sẽ nhận 60% khoảng trống mà nó có thể chiếm. Ví dụ, bạn có thể thay thế các quy tắc cho phần tử catalog trước đây bằng các quy tắc này:

catalog {
   font-family: Verdana, Arial, Helvetica, Sans-serif;
   font-size: x-small;
   background-color: #DDDDCC;
   width: 60%;
}

Giữ nguyên tất cả các quy tắc khác trong ví dụ bảng định kiểu như chúng vốn có, ta nhận được kết quả đầu ra trong trình duyệt Firefox, như thấy trong Hình 10.

Hình 10. Một phần tử chiếm một chiều rộng theo tỷ lệ phần trăm so với phần tử cha mẹ của nó
Một phần tử chiếm một chiều rộng theo tỷ lệ phần trăm so với phần tử cha mẹ của nó

Tại đây bạn có thể thấy rằng phần tử catalog thực sự chiếm 60% của khoảng trống có sẵn, trong trường hợp này là một cửa sổ trình duyệt -- vừa vặn đúng như thuộc tính width độ rộng vừa mới được thêm vào đã áp đặt.

Ems và exes là cho các đơn vị có ích để định rõ các cỡ phông chữ tương đối so với cỡ phông chữ của phần tử cha mẹ. Thủ thuật cho việc sử dụng các cỡ phông chữ này là để nhận biết rõ về cỡ của thuộc tính so sánh được của phần tử cha mẹ.

Bảng 1 tóm tắt các đơn vị độ dài tuyệt đối và tương đối.

Bảng 1. Đơn vị độ dài
Tuyệt đốiTương đối
Đơn vịMô tảĐơn vịMô tả
inInch%Phần trăm: tương đối so với chiều dài của thuộc tính cha mẹ tương ứng.
ptĐiểm: bằng 1/72 inch.emEm: số lần chiều cao của chữ M hoa ("M") của phần tử cha mẹ.
pcPica: bằng 12 điểm.exEx: số lần chiều cao của chữ x thường ("x") của phần tử cha mẹ.
cmCentimet: bằng 0,394 inch.pxPixel: Đơn vị của độ phân giải hiển thị trên màn hình. Được xem là một đơn vị tương đối do các thiết bị khác nhau có các độ phân giải và cỡ khác nhau.
mmMillimet: bằng 0,1 Centimet. 

Phông chữ

Các thuộc tính phông chữ (font) khống chế một kiểu chữ được hiển thị như thế nào. Các thuộc tính font có sẵn bao gồm:

  • font-family (họ-phông chữ): Một danh sách tên của các họ phông chữ, được phân tách bằng dấu phẩy, theo thứ tự ưu tiên. Ví dụ giá trị bao gồm Arial, Verdana, Sans-serif, Times New RomanSerif. Nếu tên của họ phông chữ gồm nhiều hơn một từ thì cần được bao bọc trong cặp dấu nháy kép khi được hiển thị. Họ phông chữ cuối cùng trong danh sách nên luôn là hoặc Sans-serif hay Serif, tùy thuộc vào cần những gì.
  • font-size: (cỡ chữ): có thể dùng đơn vị độ dài tương đối hoặc tuyệt đối. Ngoài các đơn vị tương đối và tuyệt đối được liệt kê trong Bảng 1, các giá trị xx-small, x-small, small, medium, large, x-large"xx-large" được sử dụng. Mặc dù các giá trị này đôi khi được coi như là các kích thước tuyệt đối, các trình duyệt điều chỉnh chúng theo sự lựa chọn ưu tiên của người dùng.
  • font-style (kiểu chữ): Thông thường là normal (mặc định) hoặc italic.
  • font-weight (độ đậm phông chữ): Kiểm soát việc phông chữ được hiển thị bình thường (normal) (mặc định) hay in đậm (bold). Một số trình duyệt đưa ra các điều chỉnh chữ đậm bằng các mức đậm hơnnhạt hơn.

Văn bản

Để kiểm soát các thuộc tính về kiểu chữ mà các thuộc tính phông chữ không xử lý, bạn có thể sử dụng các thuộc tính văn bản. Những thuộc tính này bao gồm:

  • color (màu sắc): Mô tả giá trị như đã nêu ra ở trên trong phần Màu sắc.
  • background-color (màu nền): Thiết lập màu sắc của vùng trực tiếp xung quanh các văn bản. Bạn có thể phóng to vùng này bằng việc sử dụng các thuộc tính padding:, được thảo luận trong phần phần đệm (Padding).
  • text-align (canh lề văn bản): Chấp nhận các giá trị bên trái (mặc định), bên phải, chính giữa hay thẳng đều cả hai bên.
  • text-decoration (trang trí văn bản): Thông thường nhận các giá trị không (none) (mặc định) hay gạch dưới (underline). Các giá trị có khả năng khác bao gồm gạch trên) overline) hoặc gạch đè (line-through). (Cũng có tin đồn về giá trị nhấp nháy (blink), mặc dù theo phép tắc bắt buộc không thảo luận tại đây).

Nền

Bạn có thể áp dụng các xử lý nền cho các phần tử nội dòng, khối và bảng thông qua thuộc tính màu nền (background-color) hoặc sử dụng các hình ảnh nền. Các giá trị của background-color tuân theo sự mô tả màu sắc trên đây. Việc sử dụng các hình ảnh, tuy nhiên, có thể có chút rắc rối hơn. Các thuộc tính được sử dụng để mô tả một hình ảnh nền bao gồm như sau::

  • background-image (hình ảnh-nền): Yêu cầu cú pháp url('image URI') để xác định vị trí hình ảnh.
  • background-position (vị trí nền): Chỉ thị về hướng của hình ảnh tương đối so với phần tử. Cú pháp cho việc định hướng này bao gồm hai khía cạnh sau đây: trái hay phảiđỉnh hay đáy.
  • background-repeat (lặp lại hình nền): Kiểm soát cách thức hình nền được tạo thành từ nhiều ảnh xếp kề nhau như thế nào, theo chiều thẳng đứng hay theo chiều nằm ngang. Cú pháp điều khiển việc này có thể là; no-repeat (không xếp kề nhiều hình ảnh) chồng lên nhau, repeat-x (xếp kề hình ảnh) theo chiều ngang, hoặc repeat-y (xếp kề hình ảnh) theo chiều thẳng đứng.

Các quy tắc sau đây cung cấp một ví dụ về cú pháp này:

background-image: url("../images/tubeTile.gif"); 
background-position: left top;
background-repeat: repeat-x;

Phần đệm thêm

Các thuộc tính phần đệm thêm (padding) làm việc đối với các phần tử nội dòng (inline) và khối (block). Bạn có thể chỉ rõ hoặc là một thuộc tính padding: hoặc bạn có thể chỉ rõ một hoặc nhiều thuộc tính trong các thuộc tính cho bốn hướng: padding-top:, padding-left:, padding-right:padding-bottom:. Bạn có thể sử dụng các đơn vị được mô tả ở trên trong phần Độ dài. Đối với một thuộc tính padding:, bạn vẫn còn có thể chỉ rõ duy nhất một trong bốn hướng bằng cách đặt các giá trị theo một thứ tự cụ thể, khi cho trước số các giá trị. Ví dụ:

  • Nếu cho một giá trị chiều dài, nó áp dụng cho tất cả bốn phía.
  • Nếu cho hai giá trị chiều dài, giá trị đầu tiên mô tả đỉnh trang và đáy trang và giá trị thứ hai mô tả lề trái và lề phải.
  • Nếu cho ba giá trị chiều dài, các giá trị mô tả đỉnh trang, lề trái và lề phải, và đáy trang theo đúng thứ tự đó.
  • Nếu cho bốn giá trị chiều dài, các giá trị mô tả đỉnh trang, lề phải, đáy trang và lề trái, theo đúng thứ tự đó.

Bạn có thể sử dụng bất kỳ sự kết hợp nào của các đơn vị chiều dài, nhưng không phải các số âm. Thuộc tính này không được thừa kế từ các phần tử cha mẹ.

Các đường viền

Tương tự với các thuộc tính padding:, bạn có thể mô tả đường viền bằng border: hoặc là tất cả xung quanh dành cho một phần tử, hoặc bằng một hay nhiều thuộc tính trong các thuộc tính cho bốn hướng: border-top:, border-left:, border-right:border-bottom:. Cú pháp giá trị là: chiều dài đường viền- kiểu-dáng màu-sắc. Các đơn vị chiều dài cho phép đã được thảo luận trước đây trong phần Độ dài. Kiểu dáng-đường viền có thể là một trong các giá trị sau đây: gạch nối (dashed), nét kép (double), nét chấm chấm (dotted), nét rãnh xoi (groove), nét lồng trong (inset), nét lồng ngoài (outset) hay nét liền (solid). Các quy tắc dưới đây đưa ra một ví dụ về cú pháp này:

border-left:   1px solid #EEEEEE;
border-right:  1px solid #999999;

Vị trí

Với các thuộc tính vị trí của CSS, bạn có thể báo cho các phần tử biết chính xác cần hiển thị ở đâu trong một tài liệu. Ví dụ, nếu bạn muốn định rõ rằng phần tử dvd đầu tiên trong danh mục (catalog) xuất hiện ở một điểm cố định so với tất cả các phần tử khác, bạn có thể sử dụng các mã sau đây:

dvd:first-child {
   border-top: 2px solid #666666;
   position: absolute;
   left:  80px;
   top:  150px;
}

Lưu ý rằng thuộc tính position giá trị của nó là tuyệt đối. Khi chỉ rõ thuộc tính này thì bạn có thể mô tả bạn muốn đặt phần tử ở vị trí nào kể từ góc trên - trái của trang. Trong quy tắc trên đây, chúng ta đã khai báo vị trí cách 80 pixel từ cạnh bên trái và cách 150 pixel từ đầu trang trở xuống. Hình 11 cho thấy khi được biểu hiện trong Firefox nó trông như thế nào.

Hình 11. Định vị tuyệt đối trong Firefox
Absolute positioning

Trong Hình 11, Terminator 2 (Kẻ hủy diệt 2) là phần tử dvd đầu tiên theo thứ tự tài liệu, do đó, nó đã nhận quy tắc định vị trí tuyệt đối đã khai báo cho phần tử dvd đầu tiên. Ngoài các thuộc tính bên trái (left) và đỉnh trang (top), bạn có thể khai báo thuộc tính bên phải (right) và đáy trang (bottom); Các khai báo này đặt phần tử ở vị trí so với cạnh bên phải hay cạnh đáy của trang, một cách tương ứng. Bạn có thể sử dụng bất kỳ kết hợp nào của các thuộc tính này, miễn là nó có ý nghĩa với việc bố trí. Một kiểu giá trị khác của thuộc tính vị trí là giá trị tương đối (relative), nó được cộng thêm vào vị trí biểu hiện bình thường của một phần tử bằng các thuộc tính top, left, rightbottom. Ví dụ, bạn có thể sử dụng mã lệnh sau đây để đặt phần tử dvd đầu tiên ở dịch lên trên và sang bên trái vị trí bình thường của nó, mỗi chiều 10 pixel:

dvd:first-child {
   border-top: 2px solid #666666;
   position: relative;
   left: -10px;
   top:  -10px;
}

Hình 12 cho thấy kết quả được biểu hiện trong Firefox trông như thế nào.

Hình 12. Định vị tương đối trong Firefox
Relative positioning in Firefox

Có thể đè lên phần hiển thị của một phần tử bởi một phần tử khác. Bạn có thể kiểm soát phần tử nào được biểu diễn trên đỉnh trang với thuộc tính z-index: Các giá trị số nguyên được sử dụng cho việc này, với phần tử có giá trị lớn hơn được đặt đè lên trên các phần tử khác.

Một cách khác để xác định vị trí các phần tử là thông qua định vị cố định. Trong khi position: absolute thiết lập vị trí một phần tử so tương đối với bố trí của các phần tử khác trong trang, thì position: fixed thiết lập vị trí phần tử so tương đối với cửa sổ trình duyệt. Điều này rất khó để trình bày ra mà không dùng một ví dụ cửa sổ có khả năng cuộn được, nhưng bạn có thể tự mình làm thử; cú pháp đơn giản là position: fixed. Các thuộc tính top, left, rightbottom cho phép bạn thiết lập vị trí của phần tử mà vẫn được giữ nguyên, thậm chí khi cửa sổ trang được cuộn.

Tóm tắt CSS

Mặc dù không phải là cách nói chung thường được ưa thích để định kiểu dáng các tài liệu XML và không có khả năng thực hiện tính toán hoặc biến đổi như là những gì XSLT có thể làm được, CSS ít nhất cung cấp một cách gọn nhẹ để định dạng trực quan các phần tử XML. Do sự hỗ trợ CSS không nhất quán (đặc biệt là cho XML) trong các trình duyệt khác nhau, hãy sử dụng CSS một cách thận trọng, ít nhất là cho phương tiện màn hình. Tuy nhiên, như ở đây đã cho thấy, hỗ trợ XML cho CSS là rất mạnh trong Mozilla Firefox. Các bài báo đã viết về CSS cho phương tiện in ấn đã cho thấy thành công lớn; điều này đặc biệt có ích nếu bạn có thể tránh được sự phức tạp của XSLT.


Kết luận

Tóm tắt

Phần này kết thúc các cuộc thảo luận về các chủ đề phép biến đổi XML như XSLT, XPath, và CSS. Hy vọng rằng thông tin này cung cấp một sự mở đầu vững chắc cho những người mới làm quen với chủ đề ấy. Một nỗ lực hợp lý để hiểu được các tư liệu được trình bày ở đây và xem xét các tài liệu tham khảo tiếp theo sẽ là trên mức đầy đủ để để chuẩn bị cho bạn về phần các phép biến đổi XML của kỳ thi số 142, XML và Các công nghệ liên quan.

Tài nguyên

Học tập

  • XML in a Nutshell, 3rd Edition (Elliotte Rusty Harold and W. Scott Means, O'Reilly Media, 09.2004, ISBN: 0596007647): Trong tài liệu tham khảo XML toàn diện này, tìm các chương xuất sắc về XSLT, XPath và CSS cho XML. Cũng có thể tìm thấy những so sánh quan trọng giữa các phiên bản 1.0 và 2.0 của XSLT và XPath.
  • XSLT Cookbook, 2nd Edition (Sal Mangano. O'Reilly, 12.2005, ISBN: 0596009747): Đào sâu vào các ví dụ chi tiết về cách sử dụng XPath và XSLT, cộng thêm một số các ứng dụng có liên quan đến các công nghệ này.
  • Universal Turing machine: Tìm hiểu tại sao XSLT là máy Turing đầy đủ trong bài Wikipedia này.
  • Investigating XSLT: The XML transformation language (LindaMay Patterson, developerWorks,08.2001): Đọc về cú pháp cơ bản và các kỹ thuật lập trình XSL trong bài viết sớm này trên XSLT và XPath.
  • Practical data binding: XPath as a data binding tool, Part 1 (Brett McLaughlin, developerWorks, 11.2005): Khám phá một sách vỡ lòng tốt về XPath và thêm vào những gì bạn đã thấy trong hướng dẫn này.
  • XSLT Transformation: Truy cập W3Schools để biết thêm về cú pháp và ngữ pháp XSLT cơ bản.
  • CSS tutorial: Tìm hiểu áp dụng kiểu dáng và bài trí cho nhiều trang web cùng một lúc từ W3Schools. Hầu hết những gì bạn làm cho mã HTML cũng được áp dụng cho XML.
  • CSS Length Units Reference (MSDN): Xem lại các đơn vị đo độ dài được hỗ trợ cho Cascading Style Sheets (CSS), văn bản, bố trí và các thuộc tính vị trí.
  • XML Transformations with CSS and DOM: Truy cập Kết nối của nhà phát triển của Apple để tìm hiểu các hỗ trợ Mozilla cho XML và CSS.
  • XPath string functions: Khám phá các hàm xử lý chuỗi ký tự với XPath trong khuyến nghị W3C này.
  • The CSS @media rule: Tìm hiểu làm thế nào để chỉ rõ các kiểu phương tiện truyền thông đích theo khuyến nghị W3C này.
  • Document order: Xem lại định nghĩa về thứ tự trong tài liệu theo XPath của W3C.
  • IBM XML 1.1 certification: Trở thành một nhà phát triển có Chứng chỉ IBM về XML 1.1 và các công nghệ liên quan.
  • XML: Xem Vùng XML của developerWorks với một dải rộng các bài viết và các lời khuyên kỹ thuật, các hướng dẫn, các tiêu chuẩn và các sách Đỏ của IBM.
  • developerWorks technical events and webcasts: Theo sát với công nghệ trong các phiên này.

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

  • Altova XMLSpy 2006 Home Edition: Tải về một trình soạn thảo XML mức mở đầu miễn phí và công cụ phát triển để thiết kế và chỉnh sửa các ứng dụng dựa trên XML.
  • Microsoft Internet Explorer 7: Tải về trình duyệt Internet Explorer 7 và các cập nhật được khuyến cáo.
  • Mozilla Firefox 1.5: Tải về Firefox 1.5 cùng với hỗ trợ của nó đối với các chuẩn Web mở.
  • IBM product evaluation versions: Tải về và thử các công cụ phát triển ứng dụng và sản phẩm phần mềm trung gian từ DB2®, Lotus®, Rational®, Tivoli® và WebSphere®.

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=972290
ArticleTitle=Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan, Phần 4: Các phép biến đổi XML
publish-date=12112009