Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan, Phần 3: Xử lý XML

Khám phá làm thế nào để phân tích cú pháp và xác nhận tính hợp lệ các tài liệu XML cộng với cách sử dụng XQuery như thế nào

Phân tích cú pháp và xác nhận tính hợp lệ là cốt lõi của XML. Biết cách làm thế nào để sử dụng tốt các khả năng này cũng là vấn đề sống còn cho việc đưa XML vào các dự án của bạn một cách thành công. Hướng dẫn này bàn về việc xử lý XML, hướng dẫn cho bạn cách làm thế nào để phân tích cú pháp và xác nhận tính hợp lệ các tệp tin XML cũng như sử dụng XQuery. Đây là hướng dẫn thứ ba 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ị cho Bài kiểm tra 142, XML và các công nghệ liên quan, để lấy chứng chỉ của IBM.

Mark Lorenz, Kiến trúc sư cao cấp, Hatteras Software, Inc.

Mark Lorenz là người sáng lập Hatteras Software, một hãng tư vấn về hướng đối tượng, và là tác giả của nhiều cuốn sách về phát triển phần mềm. Ông đã có chứng chỉ phân tích và thiết kế hướng đối tượng (OOAD), XML, RAD và Java. Ông đã sử dụng XHTML, các dịch vụ web, Ajax, JSF, Spring, BIRT, và các công cụ dựa trên Eclipse có liên quan để phát triển các ứng dụng Java doanh nghiệp



28 08 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 này 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ỉ XML và các công nghệ liên quan dành cho Nhà phát triển giải pháp có chứng nhận của IBM. 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ữ bảng đị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..

Bất cứ ai đang làm việc phát triển phần mềm trong một vài năm gần đây đều nhận thấy rằng XML mang lại khả năng xuyên qua nhiều nền tảng dành cho xử lý dữ liệu (data), cũng giống như ngôn ngữ lập trình Java® hiện với logic ứng dụng. Loạt bài hướng dẫn này dành cho bất kỳ ai, những người muốn tiến xa hơn những điều căn bản về việc sử dụng các công nghệ XML

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

Hướng dẫn này là phần thứ ba trong loạt bài "Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan" sẽ đưa bạn qua các khía cạnh chủ yếu về cách sử dụng có hiệu quả các công nghệ XML cho các dự án Java. Hướng dẫn thứ ba này tập trung vào việc xử lý XML (XML processing) -- có nghĩa là, làm thế nào để phân tích cú pháp và xác nhận tính hợp lệ các tài liệu XML. Nó đặt nền móng cho Phần 4, ở đó sẽ tập trung vào các phép biến đổi, bao gồm cả việc sử dụng XSLT, XPath và Cascading Style Sheets (CSS-Các bảng định kiểu xếp tầng).

Hướng dẫn này được viết cho các lập trình viên Java, 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. Bạn cần phải có hiểu biết chung về định nghĩa, xác nhận hợp lệ và việc đọc các tài liệu XML, cũng như các kiến thức để làm việc được với ngôn ngữ Java.

Các mục tiêu

Sau khi hoàn thành hướng dẫn này, bạn sẽ biết làm thế nào để:

  • Phân tích cú pháp các tài liệu XML bằng cách sử dụng các trình phân tích cú pháp Simple API for XML 2 (SAX2 - API đơn giản cho XML 2) và Document Object Model 2 (DOM2 – Mô hình đối tượng tài liệu 2).
  • Xác nhận hợp lệ các tài liệu XML đối với Document Type Definitions (DTD-Các định nghĩa kiểu tài liệu) và XML Schemas (Các lược đồ XML).
  • Truy cập nội dung XML từ các cơ sở dữ liệu khi sử dụng XQuery.

Các điều kiện cần có 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ủ, làm cứ liệu, định dạng, thương mại điện tử, và các ứng dụng web. Kinh nghiệm thiết kế và triển khai thực hiện các ứng dụng máy tính dựa trên Java™ và làm việc với các cơ sở dữ liệu quan hệ cũng nên có.

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

Để chạy các ví dụ trong hướng dẫn 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, các phần mềm sau đây:

  • Java software development kit 1.4.2 (JDK- Bộ công cụ phát triển phần mềm Java) hoặc mới hơn.
  • Eclipse 3.1 hoặc mới hơn.
  • XMLBuddy 2.0 hoặc mới hơn (Lưu ý: Một số phần của loạt bài viết này sử dụng các khả năng của XMLBuddy Pro, một phần mềm không miễn phí).

Xem Tài nguyên để có các kết nối đến nguồn tải về các phần mềm ở trên


Phân tích tài liệu XML

Bạn có thể phân tích cú pháp một tài liệu XML theo nhiều cách (xem Phần 1 của loạt bài này, trong đó tập trung vào kiến trúc), nhưng trình phân tích cú pháp SAX và trình phân tích cú pháp DOM là các cách làm chính. Phần 1 khắc họa một sự so sánh mức cao hai công cụ này xem Tài nguyên).

StAX

Một API mới, được gọi là Streaming API for XML (StAX- API luồng cho XML), được phát hành vào cuối năm 2006. Nó là một mô hình API kéo (pull), đối lập với mô hình đẩy (push) của SAX, vì vậy nó vẫn duy trì quyền kiểm soát với ứng dụng hơn là kiểm soát trình phân tích cú pháp. Bạn cũng có thể sử dụng StAX để sửa đổi tài liệu đang được phân tích cú pháp. Xem chi tiết hơn trong "Một giới thiệu về StAX" (xem Tài nguyên).

Cá thể tài liệu XML

Hướng dẫn này sử dụng một danh mục các đĩa DVD có sẵn để bán của một cửa hàng như là một tài liệu xuyên suốt. Theo ý tưởng thiết kế, danh mục có chứa một sưu tập các đĩa DVD có các thông tin về mỗi DVD kèm theo. Tài liệu hiện tại là một danh mục ngắn chỉ có bốn đĩa DVD trong nó, nhưng nó đủ độ phức tạp để bạn có thể tìm hiểu về việc xử lý XML, bao gồm cả việc xác nhận tính hợp lệ. Liệt kê 1 hiển thị tệp tin này.

Liệt kê 1. Cá thể tài liệu XML dành cho danh mục đĩa DVD
<?xml version="1.0"?>
<!DOCTYPE catalog SYSTEM "dvd.dtd">
<!-- DVD inventory -->
<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>

Sử dụng trình phân tích cú pháp SAX

Như Phần 1 của loạt bài này đã thảo luận, trình phân tích cú pháp SAX là một trình phân tích cú pháp dựa trên sự kiện. Điều này có nghĩa là trình phân tích cú pháp gửi các sự kiện đến các phương thức gọi lại khi nó phân tích cú pháp một tài liệu (xem Hình 1). Để đơn giản, Hình 1 không hiển thị tất cả các sự kiện sẽ thực tế xảy ra.

Hình 1. Các sự kiện của trình phân tích cú pháp SAX
Các sự kiện của trình phân tích cú pháp SAX

Những sự kiện này được đẩy tới ứng dụng theo thời gian thực, khi trình phân tích cú pháp di chuyển đi qua toàn bộ nội dung tài liệu. Một lợi ích của mô hình xử lý này là ở chỗ bạn có thể xử lý các tài liệu lớn với bộ nhớ tương đối ít. Một mặt trái của vấn đề là ở chỗ bạn có thêm nhiều việc phải làm để xử lý tất cả các sự kiện này.

Gói org.xml.sax chứa một bộ các giao diện. Một trong các giao diện này cung cấp giao diện XMLReader cho trình phân tích cú pháp. Bạn có thể thiết lập để phân tích cú pháp như thế này:

try {
    XMLReader parser = XMLReaderFactory.createXMLReader();
    parser.parse( "myDocument.xml" ); //complete path
} catch ( SAXParseException e ) { 
    //document is not well-formed
} catch ( SAXException e ) { 
    //could not find an implementation of XMLReader 
} catch ( IOException e ) { 
    //problem reading document file
}

Trình phân tích cú pháp Xerces2 của Apache

Nếu bạn cần một trình phân tích cú pháp, bạn có thể tải về trình phân tích cú pháp Xerces2 Apache mã nguồn mở từ trang Web Apache Software Foundation (xem Tài nguyên).

Lời khuyên: Sử dụng lại một cá thể trình phân tích cú pháp nếu có thể. Việc tạo ra một trình phân tích cú pháp rất tốn kém. Nếu bạn có nhiều luồng xử lý đang chạy, bạn có thể sử dụng lại các cá thể trình phân tích cú pháp từ một nhóm tài nguyên.

Tất cả điều này là tốt và vẫn còn tốt cho đến nay, nhưng ứng dụng của bạn nhận các sự kiện từ trình phân tích cú pháp như thế nào? Tôi rất vui vì bạn đã hỏi.

Xử lý các sự kiện SAX

Để nhận các sự kiện từ trình phân tích cú pháp, bạn triển khai thực hiện giao diện ContentHandler. Một cách khác, nếu bạn chỉ muốn xử lý một hoặc hai lời gọi lại, bạn có thể tạo ra một lớp con (subclass) DefaultHandler, nó triển khai thực hiện tất cả các phương thức ContentHandler (không làm bất kỳ điều gì) và ghi đè chỉ những phương thức nào bạn cần.

Dù bằng cách nào, bạn viết logic để làm bất cứ việc xử lý nào mà bạn cần khi nhận được startElement, characters, endDocument và các phương thức gọi lại khác được trình phân tích cú pháp SAX gọi. Bạn có thể xem tất cả các lời gọi phương thức từ một tài liệu khi chúng xảy ra, trên các trang 351-355 của XML in a Nutshell, Third Edition (XML tóm tắt, Ấn bản thứ ba) (xem Tài nguyên).

Các sự kiện gọi lại là những sự kiện chuẩn (normal) từ một tài liệu khi nó đang được phân tích cú pháp. Bạn cũng có thể xử lý các lời gọi lại xác nhận hợp lệ (validity) bằng cách triển khai thực hiện một ErrorHandler. Tôi sẽ thảo luận về chủ đề này sau khi đến phần xác nhận hợp lệ, do đó hãy chờ đợi.

Để tìm hiểu thêm về việc phân tích cú pháp với SAX, hãy xem Chương 20 của XML in a Nutshell, Third Edition hoặc đọc "Truy cập tuần tự bằng API đơn giản cho XML (SAX)" (xem Tài nguyên).

Xử lý lỗi ngoại lệ của trình phân tích cú pháp SAX

Theo mặc định, trình phân tích cú pháp bỏ qua các lỗi. Để hành động trên một tài liệu không hợp lệ hay không đúng ngữ pháp và cú pháp, bạn phải triển khai thực hiện một ErrorHandler (lưu ý rằng DefaultHandler triển khai thực hiện ContentHandler cũng như giao diện ContentHandler) và định nghĩa một phương thức (error():

public class SAXEcho extends DefaultHandler {
...
//Handle validity errors
public void error( SAXParseException e ) { 
    echo( e.getMessage() );
    echo( "Line " + e.getLineNumber() + 
         " Column " + e.getColumnNumber();
}

Sau đó, bạn cần phải bật đặc tính xác nhận hợp lệ:

parser.setFeature( "http://xml.org/sax/features/validation", true );

Cuối cùng, hãy gọi mã này:

parser.setErrorHandler( saxEcho );

Hãy nhớ rằng trình phân tích cú pháp (parser) là một cá thể của XMLReader. Trình phân tích cú pháp gọi phương thức error() nếu tài liệu này vi phạm một quy tắc lược đồ (DTD hoặc XML Schema).

Các phương thức ErrorHandler khác

ErrorHandler cũng có các phương thức cảnh báo (warning) nếu không vi phạm và phương thức fatalError, nếu vi phạm tính đúng ngữ pháp và cú pháp. Bình thường, bạn không cần phải làm bất cứ điều gì trong các phương thức này.

Báo lại các sự kiện SAX

Với ý nghĩa là một bài tập về các kỹ năng của trình phân tích cú pháp SAX mà bạn đã tìm hiểu, hãy sử dụng mã SAXEcho.java trong Liệt kê 2 để đưa ra các sự kiện của trình phân tích cú pháp đối với tệp tin catalog.xml.

Liệt kê 2. Báo lại các sự kiện SAX
package com.xml.tutorial;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * A handler for SAX parser events that outputs certain event 
 * information to standard output.
 * 
 * @author mlorenz
 */
public class SAXEcho extends DefaultHandler {
  public static final String XML_DOCUMENT_DTD = "catalogDTD.xml";
                                        //validates via catalog.dtd
  public static final String XML_DOCUMENT_XSD = "catalogXSD.xml";
                                        //validates via catalog.xsd
  public static final String NEW_LINE = System.getProperty("line.separator");
  protected static Writer writer;
  /**
   * Constructor
   */
  public SAXEcho() {
    super();
  }
  /**
   * @param args
   */
  public static void main(String[] args) {
    //-- Set up my instance to handle SAX events
    DefaultHandler eventHandler = new SAXEcho();  
    //-- Echo to standard output
    writer = new OutputStreamWriter( System.out );
    try {
      //-- Create a SAX parser
      XMLReader parser = XMLReaderFactory.createXMLReader();
      parser.setContentHandler( eventHandler );
      parser.setErrorHandler( eventHandler );
      parser.setFeature( 
                            "http://xml.org/sax/features/validation", true );
      //-- Validation via DTD --
      echo( "=== Parsing " + XML_DOCUMENT_DTD + " ===" + NEW_LINE );
      //-- Parse my XML document, reporting DTD-related errors
      parser.parse( XML_DOCUMENT_DTD );
      //-- Validation via XSD --
      parser.setFeature(  
                            "http://apache.org/xml/features/validation/schema", 
                             true );
      echo( NEW_LINE + NEW_LINE + "=== Parsing " + 
                            XML_DOCUMENT_XSD + " ===" + NEW_LINE );
      //-- Parse my XML document, reporting XSD-related errors
      parser.parse( XML_DOCUMENT_XSD );
    } catch (SAXException e) {
      System.out.println( "Parsing Exception occurred" );
      e.printStackTrace();
    } catch (IOException e) {
      System.out.println( "Could not read the file" );
      e.printStackTrace();
    }
    System.exit(0);    
  }
  //--Implement SAX callback events of interest (default is do nothing) --
  /* (non-Javadoc)
   * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
     * java.lang.String, java.lang.String, org.xml.sax.Attributes)
   * @see org.xml.sax.ContentHandler interface
   * Element and its attributes
   */
  @Override
  public void startElement(  String uri, 
          String localName,
          String qName, 
          Attributes attributes)
  throws SAXException {
      if( localName.length() == 0 )
        echo( "<" + qName );
      else
        echo( "<" + localName );
      if( attributes != null ) {
          for( int i=0; i < attributes.getLength(); i++ ) {
              if( attributes.getLocalName(i).length() == 0 ) {
                  echo( " " + attributes.getQName(i) + 
                             "=\"" + attributes.getValue(i) + "\"" );
              }
          }
      }
      echo( ">" );
  }
  /* (non-Javadoc)
   * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, 
   * java.lang.String, java.lang.String)
   * End tag
   */
  @Override
  public void endElement(String uri, String localName, String qName) 
       throws SAXException {
      echo( "</" + qName + ">" );
  }
  /* (non-Javadoc)
   * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
   * Character data inside an element
   */
  @Override
  public void characters(char[] ch, int start, int length) 
       throws SAXException {
      String s = new String(ch, start, length);
      echo(s);
  }
  //-- Add additional event echoing at your discretion --
  /**
   * Output aString to standard output
   * @param aString
   */
  protected static void echo( String aString ) {
      try {
          writer.write( aString );
          writer.flush();
      } catch (IOException e) {
          System.out.println( "I/O error during echo()" );
          e.printStackTrace();
      }
  }
  /* (non-Javadoc)
   * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
   * @see org.xml.sax.ErrorHandler interface
   */
  @Override
  public void error(SAXParseException e) throws SAXException {
    echo( NEW_LINE + "*** Failed validation ***" + NEW_LINE );
    super.error(e);
    echo( "* " + e.getMessage() + NEW_LINE + 
          "* Line " + e.getLineNumber() + 
               " Column " + e.getColumnNumber() + NEW_LINE +
       "*************************" + NEW_LINE );
    try {
      Thread.sleep( 10 );
    } catch (InterruptedException e1) {
      e1.printStackTrace();
    }
  }
}

Bạn có thể sử dụng mã trong SAXEcho.java để xem tất cả việc phân tích cú pháp SAX đi cùng với nhau như thế nào. Lưu ý rằng mã này không xử lý tất cả các sự kiện, do đó, không phải tất cả mọi thứ từ tài liệu gốc sẽ được báo lại (xem Liệt kê 3). Hãy xem xét giao diện ContentHandler để xem bạn có thể nhận được các thông báo khác nào.

Liệt kê 3. Kết quả xuất ra từ việc thực hiện SAXEcho
=== Parsing catalogDTD.xml ===
<catalog><dvd><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><title>The Matrix</title><price >10.95</price>
<year>1999</year></dvd><dvd><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><title>Raiders of the Lost Ark</title> <price>
14.95</price><year>1981</year></dvd></catalog> === Parsing catalogXSD.xml === <catalog> <dvd> <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> <title>The Matrix</title> <price>10.95</price> <year>1999</year> </dvd> <dvd> <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> <title>Raiders of the Lost Ark</title> <price>14.95</price> <year>1981</year> </dvd> </catalog>

Sử dụng trình phân tích cú pháp DOM

Trái với trình phân tích cú pháp SAX, trình phân tích cú pháp DOM xây dựng một cấu trúc cây, dựa vào các nội dung tài liệu XML (xem Hình 2). Để đơn giản, một số hành động phân tích cú pháp không được hiển thị.

Hình 2. Cây của trình phân tích cú pháp DOM
Cây của trình phân tích cú pháp DOM

DOM không chỉ rõ một giao diện cho trình phân tích cú pháp XML, do đó các nhà cung cấp khác nhau có các lớp trình phân tích cú pháp khác nhau. Tôi sẽ tiếp tục sử dụng trình phân tích cú pháp Xerces, trong đó có một lớp DOMParser.

Bạn có thể thiết lập một trình phân tích cú pháp DOM như thế này:

DOMParser parser = new DOMParser();
try {
    parser.parse( "myDocument.xml" );
    Document document = parser.getDocument();
} catch (DOMException e) {
    // take validity action here
} catch (SAXException e) {
    // well-formedness action here 
} catch (IOException e) {
    // take I/O action here
}

Duyệt đi qua cây DOM

DOM phải chịu một chi phí thời gian và bộ nhớ để xây dựng toàn bộ một cây tài liệu. Chi phí này được đền bù lại bởi việc bạn có thể duyệt đi qua cây theo nhiều cách và thao tác nội dung của tài liệu bằng cách sử dụng cấu trúc cây này. Hình 3 cho thấy một phần của tài liệu danh mục (catalog) dĩa DVD.

Hình 3. Duyệt đi qua cây DOM
Duyệt đi qua cây DOM

Cây có một gốc mà bạn có thể truy cập qua phương thức Document.getDocumentElement(). Từ một nút (Node) bất kỳ, bạn có thể sử dụng phương thức Node.getChildNodes() để nhận được một danh sách NodeList các nút con của Node hiện tại. Lưu ý rằng các thuộc tính không được coi là một phần tử con của Node đang chứa nó. Bạn có thể tạo ra các Node mới, nối thêm chúng, chèn chúng, định vị chúng theo tên và loại bỏ chúng. Đây chỉ là một trong số vài khả năng có sẵn.

Một trong những phương thức mạnh hơn là Document.getElementsByTagName(), nó trả về một NodeList của các Node trùng khớp trong các phần tử con cháu. Cây DOM có sẵn trên máy khách cũng như trên máy chủ.

Duyệt đi qua cây ở máy khách

Bạn có thể duyệt đi qua cây DOM trong máy khách và bạn có thể hiệu lực hóa các hành động trên một trang XHTML thông qua mã JavaScript từ bên trong trình duyệt. Ví dụ, máy khách có thể cần phải tìm hiểu xem liệu một Node có một tên cụ thể đã tồn tại chưa:

//-- make sure a new DVD's title is unique
var titles = document.getElementsByTagName("title");
var newTitleValue = newTitle.getNodeValue();
var nextTitle;
for( i=0; i < titles.getLength(); i++ ) {
    nextTitle = titles.item(i); //NodeList access by index
    if( nextTitle.getNodeValue().equals( newTitleValue ) {
        //take some action
    }
}

Duyệt đi qua cây ở máy chủ

Trên máy chủ, bạn chắc chắn cần phải thao tác cây, chẳng hạn như để thêm một nhánh con mới đến một Node:

//-- add a new DVD with aName and description
public void createNewDvd( String aName, String description ) {
    Element catalog =  document.getDocumentElement(); //root
    Element newDvd = document.createElement( aName );
    Element dvdDescription = 
                         document.createTextNode( description );
    newDvd.appendChild( dvdDescription );
    catalog.appendChild( newDvd ); //as last element
}

XHTML như là một cách thay thế

Hướng dẫn này làm việc với tài liệu dữ liệu, nhưng tài liệu có thể dễ dàng là một trang XHTML, trong trường hợp đó bạn muốn xem các Node như head, body, p, tdli.

Thận trọng: Hãy chắc chắn là đang sử dụng các giao diện DOM, chẳng hạn như NodeList hay NamedNodeMap, để thao tác cây. Cây DOM là động, có nghĩa là nó được cập nhật ngay lập tức dựa trên các thay đổi mà bạn đang làm, do đó nếu bạn sử dụng các biến cục bộ để lưu trữ sẵn các giá trị, các giá trị này có thể sai. Ví dụ, Node.getLength() trả về một giá trị khác sau một lời gọi đến removeChild().

Xử lý lỗi ngoại lệ của trình phân tích cú pháp DOM

DOM3

DOM3 đã thêm vào một DOMErrorHandler, nó cung cấp một cơ chế gọi lại để sử dụng thay cho DOMException. Sau đây là một số mã ví dụ:

DOMParser parser = new DOMParser(); DOMConfiguration domConfig = document.domConfig; domConfig.setParameter( DOMErrorHandler handler );

Lớp có triển khai thực hiện giao diện DOMErrorHandler có một phương thức handleError(DOMError error), phương thức này trả về đúng (true) để tiếp tục xử lý hay sai (false) để dừng xử lý (các lỗi nghiêm trọng (fatal) luôn luôn dừng xử lý)

Trình phân tích cú pháp DOM đưa ra một DOMException nếu có vấn đề xảy ra trong quá trình phân tích cú pháp. Đây là một RuntimeException, do một số ngôn ngữ không hỗ trợ các lỗi ngoại lệ đã kiểm tra, nhưng bạn nên luôn luôn bắt giữ nó hoặc đưa nó vào trong mã Java của bạn.

Để phát hiện vấn đề về thao tác, hãy sử dụng mã (code) của một DOMException. Các này báo cho bạn biết những gì là sai, chẳng hạn như là một sửa đổi không thành công làm cho tài liệu thành không hợp lệ (DOMException.INVALID_MODIFICATION_ERR) hoặc một Node đích không thể tìm được (DOMException.NOT_FOUND_ERR). Phần DOMException trong Chương 9 của Xử lý XML với Java: Hướng dẫn về SAX, DOM, JDOM, JAXP, và TrAX cung cấp một danh sách đầy đủ các mã DOMException code có kèm các giải thích (xem Tài nguyên).

Báo lại cây DOM

Với ý nghĩa như một bài tập các kỹ năng trình phân tích cú pháp DOM mà bạn đã học, hãy sử dụng mã DOMEcho.java trong Liệt kê 4 để đưa ra các nội dung của cây DOM của tệp tin catalog.xml. Sau khi mã này báo lại thông tin cây, rồi nó thay đổi cây và báo lại cây đã được cập nhật.

Liệt kê 4. Báo lại một cây DOM
package com.xml.tutorial;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
import org.xml.sax.SAXException;

import com.sun.org.apache.xerces.internal.parsers.DOMParser;

/**
 * A handler to output certain information about a DOM tree 
 * to standard output.
 * 
 * @author lorenzm
 */
public class DOMEcho {
  public static final String XML_DOCUMENT_DTD = 
                              "catalogDTD.xml";   //validates via catalog.dtd
  public static final String NEW_LINE = System.getProperty("line.separator");
  protected static Writer writer;
    // Types of DOM nodes, indexed by nodeType value (e.g. Attr = 2)
    protected static final String[] nodeTypeNames = {
        "none",         //0
        "Element",      //1
        "Attr",         //2
        "Text",         //3
        "CDATA",        //4
        "EntityRef",    //5
        "Entity",       //6
        "ProcInstr",    //7
        "Comment",      //8
        "Document",     //9
        "DocType",      //10
        "DocFragment",  //11
        "Notation",     //12
    };
    //-- DOMImplementation features (we only need one for now)
    protected static final String TRAVERSAL_FEATURE  = "Traversal";
    //-- DOM versions (we're using DOM2)
    protected static final String DOM_2        = "2.0";

  /**
   * Constructor
   */
  public DOMEcho() {
    super();
  }

  /**
   * @param args
   */
  public static void main(String[] args) {
        //Echo to standard output
      writer = new OutputStreamWriter( System.out );
        //use the Xerces parser
      try {
          DOMParser parser = new DOMParser();  
          parser.setFeature( "http://xml.org/sax/features/validation", true );
          parser.parse( XML_DOCUMENT_DTD ); //use DTD grammar for validation
          Document document = parser.getDocument();
          echoAll( document );
          //-- add description for Indiana Jones movie
          //---- find parent Node
          Element indianaJones = document.getElementById("_7755522");
          //---- insert a description before the price 
          //    (anywhere else would be invalid)
          NodeList prices = indianaJones.getElementsByTagName("price");
          Node desc = document.createElement("description");
          desc.setTextContent(
                      "Indiana Jones is hired to find the Ark of the Covenant");
          indianaJones.insertBefore( desc, prices.item(0)  );
          //-- now, echo the document again to see the change
          echoAll( document );
      } catch (DOMException e) {  //handle invalid manipulations
          short code = e.code;
          if( code == DOMException.INVALID_MODIFICATION_ERR ) {
              //take action when invalid manipulation attempted
          } else if( code == DOMException.NOT_FOUND_ERR ) {
              //take action when element or attribute not found
          }   //add more checks here as desired
      } catch (SAXException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
  
  /**
   * Echo all the Nodes, in preorder traversal order, for aDocument
   * @param aDocument
   */
  protected static void echoAll(Document aDocument) {
      if( aDocument.getImplementation().hasFeature(
                                        TRAVERSAL_FEATURE,DOM_2) ) {
          echo( "=== Echoing " + XML_DOCUMENT_DTD + " ===" + NEW_LINE );
          Node root = (Node) aDocument.getDocumentElement();
          int whatToShow = NodeFilter.SHOW_ALL;
          NodeFilter filter = null;
          boolean expandRefs = false;
          //-- depth first, preorder traversal 
          DocumentTraversal traversal = (DocumentTraversal)aDocument;
          TreeWalker walker = traversal.createTreeWalker(
                          (org.w3c.dom.Node) root, //where to start 
                                         //(cannot go "above" the root)
                          whatToShow,  //what to include
                          filter,       //what to exclude
                          expandRefs); //include referenced entities or not
          for( Node nextNode = (Node) walker.nextNode(); nextNode != null; 
                                        nextNode = (Node) walker.nextNode() ) {
              echoNode( nextNode );
          }
      } else {
          echo( NEW_LINE + "*** " + TRAVERSAL_FEATURE + 
                           " feature is not supported" + NEW_LINE );
      }
  }

  /**
   * Output aNode's name, type, and value to standard output.
   * @param aNode
   */
  protected static void echoNode( Node aNode ) {
    String type = nodeTypeNames[aNode.getNodeType()];
    String name = aNode.getNodeName();
    StringBuffer echoBuf = new StringBuffer();
    echoBuf.append(type);
    if( !name.startsWith("#") ) {  //do not output duplicate names
        echoBuf.append(": ");
        echoBuf.append(name);
    }
    if( aNode.getNodeValue() != null ) {
      if( echoBuf.indexOf("ProcInst") == 0 )
          echoBuf.append( ", " );
      else
          echoBuf.append( ": " );  //output only to first newline
      String trimmedValue = aNode.getNodeValue().trim();
      int nlIndex = trimmedValue.indexOf("\n");
      if( nlIndex >= 0 )  //found newline
          trimmedValue = trimmedValue.substring(0,nlIndex);
      echoBuf.append(trimmedValue);
    }
    echo( echoBuf.toString() + NEW_LINE );
    echoAttributes( aNode );
  }
  
  /**
   * Output aNode's attributes to standard output.
   * @param aNode
   */
  protected static void echoAttributes(Node aNode) {
      NamedNodeMap attr = aNode.getAttributes();
      if( attr != null ) {
          StringBuffer attrBuf = new StringBuffer();
          for( int i = 0; i < attr.getLength(); i++ ) {
              String type = nodeTypeNames[attr.item(i).getNodeType()];
              attrBuf.append(type);
              attrBuf.append( ": " + attr.item(i).getNodeName() + "=" );
              attrBuf.append( "\"" + attr.item(i).getNodeValue() + "\"" + 
                                   NEW_LINE );
          }
          echo( attrBuf.toString() );
      }
  }

  /**
   * Output aString to standard output
   * @param aString
   */
  protected static void echo( String aString ) {
    try {
        writer.write( aString );
        writer.flush();
    } catch (IOException e) {
        System.out.println( "I/O error during echo()" );
        e.printStackTrace();
    }
  }
}

Xem xét một số phần của logic xử lý:

protected static final String[] nodeTypeNames = {
    ...
};

Mảng này ánh xạ giá trị Node.getNodeType() int đến mỗi một trong các kiểu các Node mà bạn có thể bắt gặp:

if( aDocument.getImplementation().hasFeature(
                            TRAVERSAL_FEATURE,DOM_2) ) {

DOM1 so với DOM2

Trong DOM1, việc duyệt đi qua cây tài liệu (document) đã được thực hiện theo kiểu "tuyến tính" với các Node đứng trước và nút đứng sau được yêu cầu khi sử dụng các NodeIterator và các NodeFilter. Trong DOM2, giao diện TreeWalker đã thêm vào khái niệm về một Node hiện tại, với khả năng di chuyển tới cha mẹ, con và anh chị em.

Bạn có thể đọc về NodeIteratorNodeFilter cũng như TreeWalker của DOM2 trong Chương 12 của Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX (xem Tài nguyên).

Bruno R. Preiss giải thích các cách duyệt đi qua cây khác nhau (xem Tài nguyên).

DOMEcho tận dụng giao diện TreeWalker được giới thiệu trong DOM2 (xem DOM1 so với DOM2 ). Để an toàn, hãy kiểm tra để chắc chắn rằng trình phân tích cú pháp của bạn hỗ trợ đặc tính này. Bạn có thể đọc về tất cả các đặc tính có sẵn trong phần "Các mô đun DOM" trong Chương 9 của Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX (xem Tài nguyên).

Về cơ bản, DOMEcho có một phương thức echoAll(Document aDoc), phương thức này sử dụng TreeWalker không lọc để nhận lấy các Node theo thứ tự duyệt đi qua cây xác định trước (xem DOM 1 so với DOM 2). Sau đó phương thức echoNode(Node aNode) được gọi cho mỗi lần. Đến lượt nó, echoNode gọi echoAttributes(Node aNode) cho Node của nó:

//---- find parent Node
Element indianaJones = document.getElementById("_7755522");
//---- insert a description before the price 
//    (anywhere else would be invalid)
NodeList prices = indianaJones.getElementsByTagName("price");
Node desc = document.createElement("description");
desc.setTextContent(
      "Indiana Jones is hired to find the Ark of the Covenant");
indianaJones.insertBefore( desc, prices.item(0)  );

Phần mã này là những gì thay đổi cây DOM. Nó thêm một mục mô tả tại đúng vị trí để cho cây vẫn còn hợp lệ theo lược đồ của tài liệu.

Liệt kê 5 hiển thị kết quả đầu ra từ DOMEcho DOMEcho.

Liệt kê 5. Kết quả xuất ra từ DOMEcho
=== Echoing catalogDTD.xml ===
Text: 
Comment: DVD inventory
Text: 
Element: dvd
Attr: code="_1234567"
Text: 
Element: title
Text: Terminator 2
Text: 
Element: description
Text: A shape-shifting cyborg is sent back from the future 
to kill the leader of the resistance.
Text: 
Element: price
Text: 19.95
Text: 
Element: year
Text: 1991
Text: 
Text: 
Element: dvd
Attr: code="_7654321"
Text: 
Element: title
Text: The Matrix
Text: 
Element: price
Text: 10.95
Text: 
Element: year
Text: 1999
Text: 
Text: 
Element: dvd
Attr: code="_2255577"
Attr: genre="Drama"
Text: 
Element: title
Text: Life as a House
Text: 
Element: description
Text: When a man is diagnosed with terminal cancer, 
he takes custody of his misanthropic teenage son.
Text: 
Element: price
Text: 15.95
Text: 
Element: year
Text: 2001
Text: 
Text: 
Element: dvd
Attr: code="_7755522"
Attr: genre="Action"
Text: 
Element: title
Text: Raiders of the Lost Ark
Text: 
Element: price
Text: 14.95
Text: 
Element: year
Text: 1981
Text: 
Text: 
=== Echoing catalogDTD.xml ===
Text: 
Comment: DVD inventory
Text: 
Element: dvd
Attr: code="_1234567"
Text: 
Element: title
Text: Terminator 2
Text: 
Element: description
Text: A shape-shifting cyborg is sent back from the future 
to kill the leader of the resistance.
Text: 
Element: price
Text: 19.95
Text: 
Element: year
Text: 1991
Text: 
Text: 
Element: dvd
Attr: code="_7654321"
Text: 
Element: title
Text: The Matrix
Text: 
Element: price
Text: 10.95
Text: 
Element: year
Text: 1999
Text: 
Text: 
Element: dvd
Attr: code="_2255577"
Attr: genre="Drama"
Text: 
Element: title
Text: Life as a House
Text: 
Element: description
Text: When a man is diagnosed with terminal cancer, 
he takes custody of his misanthropic teenage son.
Text: 
Element: price
Text: 15.95
Text: 
Element: year
Text: 2001
Text: 
Text: 
Element: dvd
Attr: code="_7755522"
Attr: genre="Action"
Text: 
Element: title
Text: Raiders of the Lost Ark
Text: 
Element: description
Text: Indiana Jones is hired to find the Ark of the Covenant
Element: price
Text: 14.95
Text: 
Element: year
Text: 1981
Text: 
Text:

Khoảng trống (Whitespace)

Bạn sẽ nhận thấy rất nhiều Text Node tại đầu ra của DOMEcho (Liệt kê 6), nhiều nút trong số đó không có nội dung gì. Tại sao lại như vậy?

Trình phân tích cú pháp báo lại các khoảng trống (dấu cách thừa, các dấu tab và xuống dòng) có xuất hiện trong nội dung phần tử của tài liệu.

Hãy lưu ý những gì không được báo cáo lại: khoảng trống trong các phần tử, ví dụ như xung quanh thuộc tính. Không được hiển thị ở đây, nhưng cũng không được báo cáo lại, là các khoảng trống trong phần ngôn ngữ lập trình. Chú ý rằng một Text Element cho việc mô tả (description), nhưng khoảng trống lại được chuẩn hóa loại bỏ các ký tự thừa đứng trước và đứng sau nội dung không phải khoảng trống.

Các phần tử Text do khoảng trống có trong nội dung Element được gọi là khoảng trống có thể bỏ qua được. Khoảng trống có thể bỏ qua được không phải là một phần trong việc xác nhận hợp lệ, như bạn đang xem trong Hình 4.

Hình 4. Xứ lý khoảng trống
Xứ lý khoảng trống

Xác nhận hợp lệ các tài liệu XML

Việc xác nhận hợp lệ bao gồm bảo đảm đúng cấu trúc và nội dung của các tài liệu XML khi sử dụng một ngữ pháp. Bạn có thể chỉ rõ một ngữ pháp bằng cách sử dụng một lược đồ XML, lược đồ này có thể dưới dạng một tệp tin DTD hoặc XML Schema (xem Các lược đồ). Phần hướng dẫn này thảo luận về các tệp tin lược đồ DTD và XML.

Các lược đồ (Schemas)

Về mặt kỹ thuật, DTD, Lược đồ XML (XML Schemas - S chữ hoa) và RELAX NG tất cả đều là các kiểu của lược đồ XML (XML schema - s chữ thường). Lược đồ XML (XML Schemas - S chữ hoa) được gọi đầy đủ là Lược đồ XML W3C (W3C XML Schemas). Trong hướng dẫn này, bất cứ khi nào bạn nhìn thấy Lược đồ XML (XML Schema), hãy hiểu rõ rằng đó là ngôn ngữ W3C chứ không phải là mô tả tài liệu lược đồ nói chung.

Xác nhận hợp lệ khi sử dụng một DTD

Một DTD định nghĩa các ràng buộc áp đặt cho một cá thể tài liệu XML. Các ràng buộc này không liên quan đến tính đúng ngữ pháp và cú pháp. Trong thực tế, một tài liệu đã không đúng ngữ pháp và cú pháp thì không được coi như là một tài liệu XML tí nào. Các ràng buộc liên quan đến các quy tắc nghiệp vụ về nội dung mà nó phải giữ đúng cho bạn để có thể sử dụng tài liệu này với một ứng dụng.

Một DTD chỉ rõ các phần tử và các thuộc tính mà một tài liệu thể hiện XML phải có để được coi là hợp lệ. Bạn có thể kết hợp một tài liệu với một DTD bằng cách bao gồm một câu lệnh DOCTYPE gần phía trên cùng của tài liệu:

<!DOCTYPE catalog SYSTEM "catalog.dtd">

Bây giờ, hãy đi qua tệp tin catalog.dtd. Để xác nhận tính hợp lệ một tài liệu, bạn cần phải bật xác nhận hợp lệ và sử dụng một trình phân tích cú pháp xác nhận hợp lệ. Mã dưới đây bật xác nhận hợp lệ cho trình phân tích cú pháp SAX:

saxParser.setFeature(     
    "http://xml.org/sax/features/validation", true );

Với mã này, bật xác nhận hợp lệ cho trình phân tích cú pháp DOM:

domParser.setFeature( 
    "http://xml.org/dom/features/validation", true );

Hình 5 cho thấy tệp tin catalog.dtd.

Hình 5. DTD của danh mục
DTD của danh mục

Soát theo từng dòng một của DTD để xem nó chỉ rõ những gì:

<!ELEMENT catalog    (dvd+)>

dvd+ chỉ rõ rằng một phần tử <catalog> có một hoặc nhiều các <dvd>. Thật có ý nghĩa; nếu không, bạn sẽ không thể bán quá nhiều đĩa DVD được!

<!ELEMENT dvd       (title, description?, price, year)>

Tiêu đề, ..., năm (title, ..., year) được gọi là một dãy (sequence). Nó có nghĩa là các phần tử có tên cần phải xuất hiện theo đúng thứ tự này như là phần tử con của một phần tử <dvd>. Dấu hỏi sau phần tử description có nghĩa là một <dvd> có thể không có hoặc có một phần tử -- nói cách khác, nó là tùy chọn, nhưng nếu nó được định nghĩa, thì chỉ có nhiều nhất là một (một dấu hoa thị có nghĩa là không có hay có nhiều và một dấu cộng có nghĩa là có một hoặc có nhiều).

<!ATTLIST dvd  code    ID   #REQUIRED>

Một thuộc tính kiểu mã nhận dạng (ID) phải có một tên duy nhất trong tài liệu đó. Bạn sẽ nhận thấy rằng trong tệp tin catalog.xml, các ID bắt đầu bằng một dấu gạch dưới. Một tên XML không thể bắt đầu bằng một số, nhưng một dấu gạch dưới (hoặc chữ cái hay nhiều ký tự không phải là số khác) thì được. Một phần tử chỉ có thể có một kiểu ID. REQUIRED, như bạn có thể đoán, có nghĩa là một <dvd>phải có một mã (code).

<!ATTLIST dvd genre     ( Drama | Comedy | SciFi | Action | Romance ) #IMPLIED>

Đây là một bảng kê. Do nó là IMPLIED, nên nó là tùy chọn. Tuy nhiên, nếu nó thực sự xuất hiện trong tài liệu, nó phải là một trong những giá trị được liệt kê (đọc chúng như là "Drama hay Comedy hay ...").

<!ELEMENT title    (#PCDATA)>
<!ELEMENT description  (#PCDATA)>
<!ELEMENT price    (#PCDATA)>
<!ELEMENT year      (#PCDATA)>

Những dòng còn lại tất cả chỉ rõ dữ liệu ký tự được phân tích cú pháp. Không có các phần tử nào có thể có phần tử con.

Bây giờ hãy thử thay đổi cá thể tài liệu này để đảm bảo chắc chắn các quy tắc hoạt động đúng. Trước tiên, thêm một <description>, nhưng đặt nó ở cuối của <dvd>. Như mong đợi, bạn sẽ nhận được một lỗi (xem Hình 6).

Hình 6. Lỗi mô tả
Lỗi mô tả

Bây giờ, thêm một thể loại (genre) (xem Hình 7).

Hình 7. Lỗi thể loại
Lỗi thể loại

Tại sao lại không làm việc? Thể loại Khoa học viễn tưởng có trong danh sách kia mà! Ôi -- phân biệt dạng chữ, như bạn đã biết, do đó "scifi" sẽ không có tác dụng. Nó cần phải viết là "SciFi".

Bây giờ hãy kiểm tra xem các mã nhận dạng (ID) thực sự cần phải là duy nhất không. Sao chép cùng một mã (code) vào <dvd> khác (xem Hình 8).

Hình 8. Lỗi ID
Lỗi ID

Chắc chắn rồi, bạn nhận được một lỗi thích hợp. Bạn đã thấy được ý tưởng. Xin cứ tự nhiên sử dụng DTD và các tệp tin XML để thử các thay đổi khác (xem Tải về với các tệp tin nguồn).

Xử lý lỗi ngoại lệ DTD

Để xử lý các lỗi thao tác DTD, bạn phải bật xác nhận hợp lệ. Đối với Xerces, bạn đặt đặc tính xác nhận hợp lệ lược đồ nhận giá trị true:

parser.setFeature( 
    "http://apache.org/xml/features/validation/schema",     
    true );

Bạn có thể đọc về các đặc tính của trình phân tích cú pháp Xerces khác nhau tại trang web Apache Software Foundation (xem Tài nguyên). Để đọc thêm về việc xác nhận hợp lệ với các DTD, hãy xem Chương 3 của XML in a Nutshell, Third Edition (xem Tài nguyên).

Xác nhận hợp lệ với SAXEcho

Bây giờ, hãy kiểm tra việc xác nhận hợp lệ. Hãy thêm dấu chú thích để loại mục price của dvdLife as a House trong tài liệu XML và xem các kết quả, khi sử dụng cả hai tệp tin DTD và XSD để xác nhận hợp lệ. Liệt kê 6 cho thấy kết quả đầu ra.

Liệt kê 6. Kết quả thực hiện SAXEcho
=== Parsing catalogDTD.xml ===
<catalog><dvd><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><title>The Matrix</title> <price>10.95
</price><year>1999</year></dvd><dvd ><title>Life as a House </title><description> When a man is diagnosed with terminal cancer, he takes custody of his misanthropic teenage son. </description><year>2001</year> *** Failed validation *** * The content of element type "dvd" must match "(title,description?,price,year)". ************************* </dvd><dvd><title>Raiders of the Lost Ark</title ><price>14.95
</price><year>1981</year></dvd></catalog> === Parsing catalogXSD.xml === <catalog> <dvd> <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> <title>The Matrix</title> <price>10.95</price> <year>1999</year> </dvd> <dvd> <title>Life as a House</title> <description> When a man is diagnosed with terminal cancer, he takes custody of his misanthropic teenage son. </description> *** Failed validation *** * cvc-complex-type.2.4.a: Invalid content was found starting with
element 'year'. One of '{"":price}' is expected. ************************* <year>2001</year> </dvd> <dvd> <title>Raiders of the Lost Ark</title> <price>14.95</price> <year>1981</year> </dvd> </catalog>

Xác nhận hợp lệ bằng cách sử dụng một lược đồ XML

Có lẽ bạn đang tự hỏi: Nếu tôi có các DTD để bảo đảm chắc chắn cấu trúc và nội dung tài liệu là hợp lệ, thì tại sao tôi lại cần một cách khác để xác nhận tính hợp lệ tài liệu? Tôi sẽ cung cấp cho bạn một vài lý do:

  • Kiểm soát mức chi tiết trên các giá trị của phần tử và thuộc tính: Lược đồ XML (XML Schema) cho phép bạn chỉ rõ định dạng, chiều dài và kiểu dữ liệu.
  • Các kiểu dữ liệu phức tạp: XML Schema hỗ trợ việc tạo ra các kiểu dữ liệu mới và chuyên biệt hóa từ các kiểu hiện có.
  • Sự xuất hiện của phần tử: Với XML Schema, có khả năng kiểm soát mức độ chi tiết của các phần tử.
  • Các không gian tên: XML Schema làm việc với các không gian tên, chúng trở nên quan trọng đối với các tổ chức để giao kết với các tổ chức khác.

Ngôn ngữ XML Schema mạnh mẽ hơn so với ngôn ngữ DTD và do đó cũng phức tạp hơn. Một trong những khía cạnh tốt đẹp là các XML Schema được viết bằng XML, trong khi các DTD thì không.

XSD

XML Schema còn được gọi là Định nghĩa Lược đồ XML (XML Schema Definition), vì vậy phần mở rộng của tệp tin là .xsd.

Chúng ta hãy xác nhận tính hợp lệ của chính cá thể tài liệu XML mà bạn đã sử dụng trong xác nhận tính hợp lệ bằng DTD trong Liệt kê 1. Liệt kê 7 hiển thị XML Schema:

Liệt kê 7. Lược đồ XML của danh mục
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xml:lang="EN"
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <!-- Our DVD catalog contains four or more DVDs -->
  <xs:element name="catalog">
        <xs:complexType>
            <xs:sequence minOccurs="4" maxOccurs="unbounded">
                <xs:element ref="dvd"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    
    <!-- DVDs have a title, an optional description, 
a price, and a release year -->
    <xs:element name="dvd">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="title"       type="xs:string"/>
                <xs:element name="description" type="descriptionString" 
minOccurs="0"/>
<xs:element name="price" type="priceValue"/> <xs:element name="year" type="yearString"/> </xs:sequence> <xs:attribute name="code" type="xs:ID"/ > <!-- requires a unique ID --> <xs:attribute name="genre"> <!-- default = optional --> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="Drama"/> <xs:enumeration value="Comedy"/> <xs:enumeration value="SciFi"/> <xs:enumeration value="Action"/> <xs:enumeration value="Romance"/> </xs:restriction> </xs:simpleType> </xs:attribute> </xs:complexType> </xs:element> <!-- Descriptions must be between 10 and 120 characters long --> <xs:simpleType name="descriptionString"> <xs:restriction base="xs:string"> <xs:minLength value="10"/> <xs:maxLength value="120"/> </xs:restriction> </xs:simpleType> <!-- Price must be < 100.00 --> <xs:simpleType name="priceValue"> <xs:restriction base="xs:decimal"> <xs:totalDigits value="4"/> <xs:fractionDigits value="2"/> <xs:maxExclusive value="100.00"/> </xs:restriction> </xs:simpleType> <!-- Year must be 4 digits, between 1900 and 2099 --> <xs:simpleType name="yearString"> <xs:restriction base="xs:string"> <xs:pattern value="(19|20)\d\d"/> </xs:restriction> </xs:simpleType> </xs:schema>

Lưu ý rằng XML Schema can thiệp nhiều hơn so với DTD tương ứng. Thực vậy, thậm chí khi bỏ đi các chú thích và khoảng trống, lược đồ này dài hơn 50 dòng, trái ngược với lược đồ DTD chỉ dài có chín dòng. (Cứ cho là lược đồ này thực hiện kiểm tra chi tiết hơn so với DTD). Như vậy, cùng với việc kiểm soát mức độ chi tiết hơn, cũng đồng thời phức tạp hơn -- phức tạp hơn rất nhiều. Thông điệp gửi đến bạn là: Nếu nhu cầu xác nhận hợp lệ của bạn không yêu cầu một XML Schema, hãy sử dụng một DTD.

Hãy xem lại danh sách giá trị gia tăng cho XML Schema để thấy các tài liệu danh mục đĩa DVD được hưởng lợi ích như thế nào, ngoài việc củng cố các ràng buộc có thể so sánh được từ DTD mà bạn đã sử dụng trước đó:

  • Kiểm soát ở mức chi tiết về các giá trị của phần tử và thuộc tính: Không giống như DTD, cho phép các giá trị ký tự bất kỳ, các XSD ràng buộc các giá trị của các mô tả (20 đến 120 ký tự), giá cả (0,00 đến 100,00) và các năm (1900 đến 2999).
  • Các kiểu dữ liệu phức tạp: Bạn đã tạo ra các kiểu dữ liệu mà bạn có thể tái sử dụng và mở rộng hơn nữa: dvd, descriptionString, priceValueyearString.
  • Sự xuất hiện của phần tử: Vì hướng dẫn này có một tài liệu nhỏ, tôi thiết lập số lượng các DVD là bốn hoặc nhiều hơn sao cho tài liệu này sẽ là hợp lệ. Trong thực tế, số lượng nhỏ nhất có thể là một con số lớn hơn nhiều, nhưng bạn có thể thấy rằng các kiểu ràng buộc này là hoàn toàn có thể.
  • Các không gian tên: Bạn chỉ được sử dụng các không gian tên cho các kiểu XML Schema, nhưng do XML Schema là nhận biết được không gian tên, nên bạn biết rằng bạn có thể bổ sung thêm nhiều không gian tên để kiểm soát các xung đột tên.

Hãy thảo luận thêm một số điểm về XML Schema để hiểu nội dung của nó:

  • xs:complexTypexs:simpleType. Một complexType là một phần tử có chứa các phần tử khác hoặc các thuộc tính khác:

    <xs:element name="dvd">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="title" type="xs:string"/>
      ...

    Một simpleType là một phần tử chỉ chứa văn bản và các giá trị thuộc tính riêng của nó:

    <xs:simpleType name="yearString">
        <xs:restriction base="xs:string">
            <xs:pattern value="(19|20)\d\d"/>
        </xs:restriction>
    </xs:simpleType>

    Trong trường hợp cụ thể này, bạn định nghĩa một kiểu mới được gọi là yearString phải có bốn chữ số và bắt đầu bằng hoặc là "19" hoặc là "20." Bạn sử dụng phần tử xs:restriction để lấy ra một kiểu được ràng buộc, mới từ một kiểu hiện có (cơ sở). Bạn sử dụng phần tử khía cạnh (facet) xs:pattern để so sánh các giá trị để xem xem chúng có phù hợp với biểu thức đã quy định chưa (xem Facets).

  • xs:sequence. Các phần tử con phải xuất hiện theo đúng thứ tự được liệt kê (mặc dù minOccurs có thể làm cho một phần tử là tùy chọn, như bạn đã thấy):

    <xs:sequence>
        <xs:element name="title"       type="xs:string"/>
        <xs:element name="description" type="descriptionString" minOccurs="0"/>
        <xs:element name="price"       type="priceValue"/>
        <xs:element name="year"        type="yearString"/>
    </xs:sequence>

    Phần tử sequence khai báo rằng các dvd trong một tài liệu hợp lệ phải có một tiêu đề (title), tiếp theo là tùy chọn có hoặc không có một phần tử description có từ 10 đến 120 ký tự, theo sau là một giá cả (price) thấp hơn US$100 với định dạng "nn.nn" và cuối cùng là một năm (year).

Facets

Lược đồ hỗ trợ một tập hợp các khía cạnh có thể đối với các giá trị. Các khía cạnh này được gọi là các facets và được sử dụng với một sự hạn chế để ràng buộc các giá trị hợp lệ. Các kiểu facet sau đây luôn có sẵn:

  • pattern
  • enumeration
  • minLengthmaxLength
  • minInclusive, maxInclusive, minExclusivemaxExclusive
  • totalDigitsfractionDigits
  • whiteSpace

Lưu ý: Việc xác nhận hợp lệ cho các XML Schema cần dùng XMLBuddy Pro.

Bây giờ thực hiện một số sửa đổi và kiểm tra xem các ràng buộc của bạn có được tuân theo không. Thêm một thể loại (genre) về Adventure, nhập một description dài hơn 120 ký tự và lặp lại một (dvd code) (xem Hình 9).

Hình 9. Các lỗi XSD
XSD errors

Bạn có thể thấy rằng thể loại (genre), mã nhận dạng ID duy nhất và chiều dài description tất cả được tuân theo.

XML Schema có nhiều khả năng hơn nữa. Dưới đây là một vài điểm nổi bật:

  • xs:choice: Một trong những phần tử con phải xuất hiện.
  • xs:all: Mỗi một trong các phần tử con được liệt kê phải xuất hiện một lần, nhưng chúng có thể xuất hiện theo thứ tự bất kỳ nào.
  • xs:group: Một tập hợp các phần tử của tên nhóm có thể được định nghĩa và sau đó được tham chiếu (qua ref=groupName).
  • xs:attributeGroup: Đây là chỉ thị tương ứng cho các thuộc tính, giống như xs:group dành cho các phần tử.
  • xs:date: Đây là một ngày tháng của lịch Gre-goa như được định nghĩa trong tiêu chuẩn ISO 8601, theo định dạng như là YYYY-MM-DD.
  • xs:time: Thời giờ được biểu diễn bằng hh: mm:ss, có hoặc không có "Z" dành cho múi giờ tương đối so với UTC.
  • xs:duration: Một số lượng các năm, các tháng, các ngày, các giờ và các phút.

Như bạn có thể thấy, rất nhiều khả năng làm sẵn đã có khi bạn viết một XML Schema. Bạn không tìm thấy những gì bạn cần ư? Hãy tạo ra một kiểu mới.

Các kiểu dữ liệu

Một đặc tính mạnh mẽ của XML Schema là khả năng để tạo ra các kiểu dữ liệu mới. Bạn đã thấy các kiểu mới được sử dụng rộng rãi trong tệp tin catalog.xsd, bao gồm cả việc tạo ra các kiểu yearStringpriceValue. Ở đây, các kiểu này chỉ được sử dụng trong kiểu dvd, nhưng bạn có thể sử dụng nó ở bất kỳ nơi nào mà trong tài liệu có xuất hiện các năm (year) hay các giá cả (price).

Các kiểu này mở rộng các kiểu chuỗi ký tự và số thập phân hiện có:

    <!-- Price must be < 100.00 -->
    <xs:simpleType name="priceValue">
        <xs:restriction base="xs:decimal">
            <xs:totalDigits    value="4"/>
            <xs:fractionDigits value="2"/>
            <xs:maxExclusive   value="100.00"/>
        </xs:restriction>
    </xs:simpleType>

    <!-- Year must be 4 digits, between 1900 and 2099 -->
    <xs:simpleType name="yearString">
        <xs:restriction base="xs:string">
            <xs:pattern value="(19|20)\d\d"/>
        </xs:restriction>
    </xs:simpleType>

Như tôi đã đề cập trước đó, bạn có thể chuyên biệt hóa một kiểu hiện có bằng cách sử dụng phần tử hạn chế (restriction) kết hợp với một hay nhiều facet. Nếu có nhiều hơn một facet tồn tại, bạn có thể sử dụng kết hợp chúng để xác định các giá trị nào là hợp lệ và các giá trị nào là không hợp lệ.

Làm cho phù hợp với mẫu

Phần tử facet mẫu hỗ trợ cú pháp biểu thức phong phú, nó tương tự như Perl. Bạn đã thấy nó được sử dụng cho yearString, ở đó bạn có thể đọc mẫu "(19|20)\d\d" như là "chuỗi ký tự phải bắt đầu bằng hoặc là một-chín hoặc là hai-không và phải được tiếp theo bằng hai số thập phân". Bảng 1 chỉ ra thêm một vài mẫu.

Bảng 1. Các biểu thức phối hợp mẫu của XML Schema
MẫuLàm cho phù hợp với
(A|B)Một chuỗi phù hợp với A hoặc B.
A?Không xuất hiện hay chỉ có một xuất hiện của một chuỗi phù hợp với A.
A*Không xuất hiện hay có nhiều xuất hiện của một chuỗi phù hợp với A.
A+Có một hay nhiều xuất hiện của một chuỗi phù hợp với A.
[abcd]Một ký tự phù hợp với một ký tự cụ thể.
[^abc]Một ký tự khác với các ký tự đã chỉ rõ.
\tMột ký tự tab.
\\Một ký tự gạch xiên ngược.
\cMột ký tự tên XML.
\sMột ký tự khoảng trống, tab, xuống dòng hoặc đầu dòng.
.Mọi ký tự bất kỳ trừ ký tự xuống dòng hoặc đầu dòng.

Để đọc thêm về các khả năng cho các biểu thức, xem các trang 427-429 của XML in a Nutshell, Third Edition hoặc xem Bảng 24-5 trong Chương 24 của XML Bible, Second Edition trực tuyến (xem Tài nguyên).

Xử lý lỗi ngoại lệ XSD

Để xử lý các lỗi thao tác của XML Schema, bạn phải bật xác nhận hợp lệ. Đối với Xerces, thiết lập đặc tính xác nhận hợp lệ của lược đồ là true:

parser.setFeature( 
    "http://apache.org/xml/features/validation/schema",     
    true );

Bạn có thể đọc về các đặc tính khác của trình phân tích cú pháp Xerces trên trang Web Apache Software Foundation (xem Tài nguyên).

Trước đó tôi đã thảo luận về các DOMException có thể xuất hiện do các vấn đề thao tác. của DOMException chỉ ra kiểu vấn đề nào đã xuất hiện.

Rà soát lại DOMEcho

Hãy thay đổi logic của DOMEcho.java để gây ra một lỗi DOMException. Dưới đây là logic mới:

//---- find parent Node
Element indianaJones = document.getElementById("_7755522");
//---- insert a description before the price 
//    (anywhere else would be invalid)
NodeList years = indianaJones.getElementsByTagName("price");
Node desc = document.createTextNode(
        "Indiana Jones is hired to find the Ark of the Covenant");
        // This change will now fail validation.
indianaJones.insertBefore( desc, indianaJones  );

Điều này dẫn đến mã sau đây đang được thi hành:

short code = e.code;
...
} else if( code == DOMException.NOT_FOUND_ERR ) {
  //take action when element or attribute not found
  echo( "*** Element not found" );
  System.exit(code);
}

Để đọc thêm về việc xác nhận hợp lệ với XML Schema, hãy xem Chương 17 của XML in a Nutshell, Third Edition, W3Schools hay "Các hướng dẫn về XML tương tác - Interactive XML tutorials" (xem Tài nguyên).


Sử dụng XQuery

Truy vấn XML (XQuery) là một ngôn ngữ để viết các biểu thức có trả về các kết quả phù hợp từ dữ liệu XML, thường trong một cơ sở dữ liệu. Các chức năng giống như thế được cung cấp bởi SQL cho nội dung không phải XML:

"Giống như SQL, XQuery chứa các chức năng để trích xuất, tóm tắt, gộp nhóm và nối dữ liệu từ nhiều bộ dữ liệu".
--"Lý thuyết và thực hành Java: Screen-scraping với Xquery" của Brian Goetz (xem Tài nguyên)

XQuery mở rộng dựa trên các biểu thức Xpath mà phần thứ tư của hướng dẫn này về các chuyển đổi XML (XML transformations) sẽ thảo luận chi tiết. Một biểu thức XPath cũng là một biểu thức XQuery hợp lệ. Vì vậy, tại sao bạn cần XQuery? Giá trị gia tăng thêm cho XQuery là do các mệnh đề mà Xquery bổ sung thêm vào các biểu thức của nó, có tính đến các biểu thức phức tạp hơn, giống như câu lệnh SELECT làm trong SQL.

Các mệnh đề XQuery

XQuery có chứa nhiều mệnh đề, được biểu diễn bằng các từ viết tắt FLWOR: for, let, where, order by, return. Bảng 2 cho thấy các phần này.

Bảng 2. Các mệnh đề FLWOR
Mệnh đềMô tả
forBạn sử dụng cấu trúc lặp này để gán các giá trị cho các biến được sử dụng trong các mệnh đề khác. Bạn khai báo các biến đó bằng một ký hiệu đồng đô la, ví dụ như $name, và nhận các giá trị được gán cho chúng từ các kết quả tìm kiếm.
letBạn sử dụng một mệnh đề let để gán một giá trị cho một biến ở bên ngoài của một mệnh đề for.
whereGiống như trong SQL, bạn sử dụng một mệnh đề where để lọc các kết quả dựa trên một số tiêu chuẩn.
order byBạn sử dụng mệnh đề này để quyết định sắp xếp các tập hợp kết quả (tăng lên - ascending hoặc giảm đi - descending) như thế nào.
returnBạn sử dụng mệnh đề return để xác định các nội dung kết quả đầu ra của truy vấn. Các nội dung có thể bao gồm các nguyên bản, các nội dung tài liệu XML, đánh dấu HTML hoặc nhiều khả năng khác.

XQuery có chứa một điều kiện, được đánh giá là đúng (true) hay sai (false) và bao gồm các tiêu chuẩn tìm kiếm trong các mệnh đề FLWOR. Hãy xem xét một số ví dụ. Bạn có thể sử dụng tệp tin dvd.xml hiển thị trong Liệt kê 8 như là cá thể tài liệu XML.

Liệt kê 8. dvd.xml
<?xml version="1.0"?>
<!-- DVD inventory -->
<catalog>
    <dvd code="1234567">
        <title>Terminator 2</title>
        <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">
        <title>Life as a House</title>
        <price>15.95</price>
        <year>2001</year>
    </dvd>
    <dvd code="7755522">
        <title>Raiders of the Lost Ark</title>
        <price>14.95</price>
        <year>1981</year>
    </dvd>
</catalog>

Saxon

Bạn có thể nhận được các công cụ SAXon miễn phí tại SAXonica nếu bạn muốn tự mình thử nghiệm XQuery (xem Tài nguyên).

Để thử việc này, tôi đã sử dụng các công cụ Xquery của SAXon. Tất cả các tệp tin của tôi đang có trong thư mục mà tôi đã giải nén SAXon vào trong đó. Để sử dụng XQuery tạo ra một trang HTML liệt kê tất cả các tiêu đề DVD theo thứ tự tăng dần, tôi đã sử dụng tệp tin dvdTitles.xq được hiển thị trong Liệt kê 9, trong đó cũng cho thấy kết quả đầu ra. Tôi đã sử dụng các lệnh sau đây để thực hiện truy vấn này:

java -cp saxon8.jar net.sf.saxon.Query -t dvdTitles.xq > dvdTitles.html
Liệt kê 9. XQuery để liệt kê các tiêu đề đĩa DVD theo thứ tự tăng dần
dvdTitles.xq:

<html>
<body>
  Available DVDs:
  <br/>
  <ol>
  {
  for $title in doc("dvd.xml")/catalog/dvd/title
    order by $title
    return <li>{data($title)}</li>
  }
  </ol>
</body>
</html>

                    dvdTitles.html:

<?xml version="1.0" encoding="UTF-8"?>
<html>
   <body>
  Available DVDs:
  <br/>
      <ol>
         <li>Life as a House</li>
         <li>Raiders of the Lost Ark</li>
         <li>Terminator 2</li>
         <li>The Matrix</li>
      </ol>
   </body>
</html>

Trong Liệt kê 9, hãy xem xét chi tiết logic của XQuery. Trước hết, truy vấn phải được bao quanh bởi các dấu ngoặc móc ("{}"). Bạn có thể nhìn thấy trong ví dụ này có ba trong số các mệnh đề được sử dụng (for, order byreturn). Bạn sử dụng hàm doc() để mở một tài liệu XML. $title là một biến được thiết lập cho từng kết quả tìm kiếm trong mỗi vòng lặp. Trong trường hợp này, nó được thiết lập là kết quả của biểu thức /catalog/dvd/title -- tên của nó là như vậy. Hàm data() trong mệnh để return chỉ lấy ra giá trị từ XML mà không có các thẻ. Nếu bạn chỉ cần đặt $title, bạn sẽ nhận được "<title>value</title>," mà bạn không muốn có trong kết quả HTML của bạn. Lưu ý rằng XQuery được bao quanh với tất cả các mã HTML cần thiết để hoàn tất trang.

Bây giờ, giả sử bạn muốn đưa ra kết quả các mức giá cho DVD có giá cao hơn 15 Đôla Mỹ (US$15) theo thứ tự giảm dần. Liệt kê 10 cho thấy tệp tin XQuery và kết quả đầu ra.

Liệt kê 10. Các giá DVD > US$15 theo thứ tự giảm dần
dvdPriceThreshold.hq

<html>
<body>
  DVDs prices below $15.00:
  <br/>
  <ol>
  {
  for $price in doc("dvd.xml")/catalog/dvd/price
    where $price < 15.00
    order by $price descendingreturn <li>{data($price)}</li>
  }
  </ol>
</body>
</html>

                    dvdPrices.html

<?xml version="1.0" encoding="UTF-8"?>
<html>
   <body>
   DVDs prices below $15.00:
  <br/>
      <ol>
         <li>14.95</li>
         <li>12.95</li>
      </ol>
   </body>
</html>

Sự khác biệt chính với truy vấn này là bạn đã chỉ rõ một mệnh đề where. Chỉ để cho vui, bạn cũng nên đảo ngược lại thứ tự sắp xếp.

Rõ ràng, bạn có thể làm nhiều hơn để tìm hiểu sức mạnh của XQuery, nhưng tôi đã trình bày đủ để chỉ ra cho bạn thấy một số trong những khả năng của nó. Để biết thêm chi tiết, hãy xem "XQuery" và "Năm ứng dụng thực hành XQuery" (xem Tài nguyên).


Kết luận

Cốt lõi của XML là phân tích cú pháp và xác nhận hợp lệ. Biết cách làm thế nào để sử dụng tốt các khả năng này là cốt yếu cho việc mở đầu thành công về XML cho dự án của bạn.

Tóm tắt

Trong hướng dẫn này về xử lý XML, bạn đã thấy làm thế nào để:

  • Phân tích cú pháp tài liệu XML khi sử dụng các trình phân tích cú pháp SAX2 và DOM2.
  • Xác nhận hợp lệ các tài liệu XML dựa vào các DTD và các XML Schema.
  • Truy cập nội dung XML từ các cơ sở dữ liệu bằng cách sử dụng Xquery.

Tải về

Mô tảTênKích thước
Sample DTD and XML filesx-cert1423-code-samples.zip16KB

Tài nguyên

Học tập

  • XML and Related Technologies certification prep (developerWorks, August - 10.2006): Với loạt bài gồm năm hướng dẫn này, hãy chuẩn bị làm Bài kiểm tra để cấp chứng chỉ số 142 của IBM, để nhận được chứng chỉ XML và các công nghệ liên quan dành cho Nhà phát triển giải pháp có chứng nhận của IBM.
  • XML: A Manager's Guide, Second Edition (Kevin Dick, Addison-Wesley Professional, 2002): Hãy đọc về việc sử dụng các công nghệ XML trong các ứng dụng doanh nghiệp.
  • XML in a Nutshell, 3rd Edition (Elliotte Rusty Harold and W. Scott Means, O'Reilly Media, 2004, ISBN: 0596007647): Xem phần tham khảo XML toàn diện này với tất cả mọi thứ từ các quy tắc cú pháp cơ bản, DTD và việc tạo lược đồ XML, các chuyển đổi XSLT, xử lý các API, XML 1.1, cộng với SAX2 và DOM Mức 3.
  • XQuery (Jim Keogh and Ken Davidson, McGraw-Hill/Osborne, 2005; ISBN: 0072262109): Hãy tìm hiểu cách viết các biểu thức Xquery trong phần này từ chương 9 của cuốn sách XML DeMYSTiFieD.
  • Five Practical XQuery Applications (Tim Matthews and Srinivas Pandrangi, 9.05.2003): Thêm Xquery vào ứng dụng của bạn để làm đơn giản hóa các nhiệm vụ khó khăn hay buồn tẻ.
  • An Introduction to StAX (Elliotte Rusty Harold, O'Reilly Media, 17.09.2003): Hãy đọc nhiều hơn về API Streaming cho XML (StAX) trong bài viết này.
  • Interactive XML tutorials: Nghiên cứu nhiều loại chủ đề XML bao gồm, SVG, DTD, lược đồ, XSLT, DOM và SAX bao gồm các vấn đề của sinh viên, truy nhập tới các trình phân tích cú pháp trực tuyến để xử lý các câu trả lời của bạn để trả về ngay lập tức.
  • W3Schools online Web tutorials: Tìm ra các hướng dẫn xây dựng Web, từ HTML và XHTML cơ bản đến XML, SQL, Database, Multimedia và WAP cao cấp.
  • Java theory and practice: Screen-scraping with XQuery (Brian Goetz, developerWorks, 22.03.2005): Tìm hiểu cách bạn có thể sử dụng XQuery như một máy trích dữ liệu hiển thị (screen-scraping) từ HTML hiệu quả như thế nào.
  • Power your mashups with XQuery (Ning Yan, developerWorks, 06.2006): Tạo ra một ứng dụng trộn lẫn (mashup) có sử dụng XQuery để ghép nội dung Web với dữ liệu XML và các dịch vụ Web.
  • The Java XML Validation API (Elliotte Rusty Harold, developerWorks, 08.2006): Kiểm tra các tài liệu XML của bạn về mức tuân thủ các lược đồ bằng API kiểm tra hợp lệ.
  • Saxonica: XSLT and XQuery Processing: Tìm hiểu về bộ sưu tập các công cụ này để xử lý các tài liệu XML bao gồm các bộ xử lý XSLT 2.0, XPath 2.0, XQuery 1.0 và XML Schema 1.0.
  • DOMException từ chương 9 của Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX (Elliotte Rusty Harold, Addison-Wesley Professional, 2002): Đọc về lỗi ngoại lệ DOMException -- lỗi thời gian chạy chung nhất.
  • DOM Modules phần trong chương 9 của Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX (Elliotte Rusty Harold, Addison-Wesley Professional, 2002): Đọc về 14 mô đun trong 8 gói khác nhau của DOM2.
  • Chapter 12, The DOM Traversal Module chương 12 của Processing XML with Java: A Guide to SAX, DOM, JDOM, JAXP, and TrAX (Elliotte Rusty Harold, Addison-Wesley Professional, 2002): Nghiên cứu sâu bộ sưu tập các giao diện tiện ích, thực hiện hầu hết logic duyệt đi qua cây DOM để làm cho chương trình của bạn đơn giản hơn.
  • Setting Features: Đọc cách thiết lập và truy vấn các đặc tính từ Apache Software Foundation, 2005.
  • Serial Access with the Simple API for XML (SAX): Khám phá SAX -- cơ cấu truy cập-tuần tự, dựa theo sự kiện để truy cập các tài liệu XML.
  • Tree traversals: Bruno R. Preiss Giải thích các cách duyệt đi qua cây khác nhau.
  • XML Bible, Second Edition (Elliotte Rusty Harold): Đọc Bảng 24-5 trong chương 24 để biết ngữ pháp của các ký hiệu trong biểu thức chính quy cho lược đồ XML.
  • 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ệ

  • Apache Xerces2 parser: Tải về mã nguồn mở của trình phân tích cú pháp tuân theo XML có bao gồm khung công tác Xerces Native Interface (XNI-Giao diện được thiết kế riêng cho Xerces) để xây dựng các cấu hình và các thành phần của trình phân tích cú pháp.
  • Java software development kit (JDK) 1.4.2 or later: Tải về bộ công cụ JDK để xây dựng các ứng dụng, các applet và các dịch vụ Web tương tác lẫn nhau, dựa trên các tiêu chuẩn.
  • Eclipse 3.1 or later: Tải về nền tảng phát triển mở rộng, nguồn mở này và các khung công tác của ứng dụng để xây dựng phần mềm.
  • XMLBuddy 2.0 or later: Tải về và bắt đầu làm việc với công nghệ có liên quan đến XML bao gồm XML, DTD, Lược đồ XML, RELAX NG, cú pháp nén RELAX NG và XSLT. Bạn có thể nhận được XMLBuddy như là trình cắm thêm của Eclipse.

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=972938
ArticleTitle=Chuẩn bị thi chứng chỉ XML và các công nghệ có liên quan, Phần 3: Xử lý XML
publish-date=08282009