Hiển thị các bài đăng có nhãn Lập trình. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Lập trình. Hiển thị tất cả bài đăng

Thứ Tư, 16 tháng 11, 2011

PHP Zend search lucene tiếng việt Unicode

PHP zend search lucene tiếng Việt Unicode

I/ Search lucene ?

Mô hình search giống như dữ liệu chính xác (có thể gần giống như google) hay giống như full-text search. Search lucene đã có những phiên bản hỗ trợ với nhiều ngôn ngữ khác nhau. Java, .Net, .PHP các bạn có thể thao khảo thêm trên http://lucene.apache.org hoặc trên wiki http://vi.wikipedia.org/wiki/Lucene,…vv


II/ PHP search lucene

Ở đây tôi dùng thư viện zend_search_lucene, đã hỗ trợ Unicode tiếng Việt khá tốt.
Cũng như các ngôn ngữ khác zend search lucene gỗm có 2 phần
1/ Phần index (công việc phân tích đánh dấu chỉ mục tài liệu)
2/ Phần search (công việc tìm kiếm trên các file dữ liệu mà bạn đã phân tích ở phần 1)

III/ Hướng dẫn cách sử dụng zend search lucene

Các bạn download thư viện zend trên trang của zend, hiện tại tôi đang dùng zend framework version 1.10.5 http://framework.zend.com/download/webservices

Nếu project của bạn sử dụng zend framework thì không cần bàn thêm, ngược lại nếu bạn sử dụng framework khác thì bạn tìm cách load thư viện zend phù hợp với framework mà bạn đang dùng, và bạn cũng có thể bỏ bớt một số libraries không cần thiết (Acl, Amf, Cloud, CodeGenerator, Console, ..vv). Nhưng nhớ phải giữ lại các libraries liên quan zend_search_luene (Application, Controller, Date, Feed, File, Loader, Locale, Memory, Mime, Search, Server, Service, Soap, Text) Còn lại có xóa bỏ bớt cho cho nhẹ host.

1/ Phần 1 index
Ví dụ:


$arr_data = array() // là dữ liệu bạn cần index để sử dụng cho phần 2 ‘searching’. Bạn có thể lấy từ CSDL MySQL.


$lucene_index_path = ‘c:\xampp\htdocs\my_project\lucene_index'; (Window & Xampp)
//$lucene_index_path = ‘/var/home/my_project/lucene_index'; (Host linux)


$index = new Zend_Search_Lucene($lucene_index_path, true);
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());


foreach($arr_data as $test) {
//create an cache index doc
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Keyword('prId', $test->prId, 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::Text('products', $test->products, 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::Text('product_desc', $test->product_desc, 'UTF-8'));
$doc->addField(Zend_Search_Lucene_Field::Keyword('lastUpdate', $test->lastUpdate, 'UTF-8'));


$index->addDocument($doc);
}


$index->commit();
$index->optimize();
echo $index->count().' Documents indexed.';

Tại sao lại dùng Keywor, Text, … các bạn tham khảo table bên dưới:

Field Type
Stored
Indexed
Tokenized
Binary
Keyword
yes
yes
no
no

UnIndexed
yes
no
no
no

Binary
yes
no
no
yes

Text
yes
yes
yes
no

UnStored
no
yes
yes
no


Hoặc xem ở thêm tại Link sau: http://darksleep.com/lucene/,

- $test->lastUpdate: là dự liệu kiểu số tôi tính toán từ cơ sở dữ liệu MySQL
// SELECT DATEDIFF(CURRENT_DATE(), product_date_add) AS lastUpdate FROM products,
Tôi thêm lastUpdate để làm ví dụ sort cho zend lucene search ở phần 2 (searching)

2/ Phần 2 searching
Ví dụ:

$lucene_index_path = ‘c:\xampp\htdocs\my_project\lucene_index'; (Window & Xampp)
//$lucene_index_path = ‘/var/home/my_project/lucene_index'; (Host linux)


Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive());
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('UTF-8');
$index = Zend_Search_Lucene::open($lucene_index_path);


$query = ‘products: Sản phẩm’;


$hits = $index->find($query, 'lastUpdate', SORT_NUMERIC, SORT_ASC);
$totals = count($hits); //total rows


foreach ($hits as $hit){
print_r($hit);
//echo $hit->prId;
//$hit->products;
//$hit->product_desc;
//$hit->lateUpdate;
}

Có một vấn đề không biết có phải host share bị giới hạn execute_time. Nếu dữ liệu tìm thấy quá lớn thì zend_search_lucene không thể chạy. Trường hợp này bạn phải sử dụng thêm chức năng giới hạn.

setResultSetLimit // đặt set limit ngay sau khi lệnh Open

Zend_Search_Lucene::open(‘’);
Zend_Search_Lucene::setResultSetLimit(350);


nhantam
PHP Developer



tag: php search lucene, zend lucene search, thuat toan tim kiem

Thứ Sáu, 23 tháng 9, 2011

Zend Currency convert VND symbol

convert VND có dấu chấm

zend v 1.11
$value = 200000 (hai trăm ngàn)
Nếu như thông thường thì zend hiển thị symbol: 200,000 đ như USD.


$currency = new Zend_Currency(array(
                           'value'      =>$value,
                           'currency'   =>'VND',
                           'symbol'      =>'đ',
                           'display'   =>2,
                           'precision'   =>0,
                           'number_format' => '#.##0.00',
                           'locale'      =>'de',
                           'position'   =>Zend_Currency::RIGHT));     

echo $currency;

Ví dụ trên xuất ra: 200.000 đ
Người Việt mình quen định dạng hàng ngàn là dấu chấm (.)

Author: nhantam

tag: Zend hiển thị tiền Đồng, Zend Currency convert VND symbol

Zend load view template, zend load email template

zend load view template kết hợp với smarty

//zend controller
function sendmailAction()
{
$row = model->query...vv
$newPass = 123;
//load view
$view = $this->getHelper('ViewRenderer')->view;
$view->fullname  = $row['fullname'];
$view->email = $row['email'];
$view->password = $newPass;
$content = $view->render('mail/forgot_password.php');
//end load view
print_r($content);
}

//forgot_password.php

Hello: {$fullname};
account: {$email};
password: {$email};

Author: nhantam

tag: zend load view template kết hợp với smarty, zend load email template

Thứ Sáu, 16 tháng 9, 2011

MySQL lấy những thành viên chưa mua sản phẩm nào (LEFT JOIN)

ví dụ ta có 2 bảng dữ  liệu
member()
memID    Name
  1       Nguyen
    2      Tran
    3      Ly
order_product()
ID  memID  product
1     1                  sp1
2     3                 sp2

Yêu cầu: truy vấn lấy ra member chưa mua sản phẩm nào. Tối ưu câu truy cấn MySQL vớiLEFT JOIN
SELECT  member.FROM   member LEFT  JOIN order_product 
ON     member.memberID= order_product.memberID 
WHERE   order_product.memberID IS NULL;
//output
memID    Name
      2      Tran

Các cách đánh indexes cho trường trong CSDL MySQL


Một ngày kia bạn nhận ra rằng website của bạn chạy chậm đi, có thể là do đường truyền nhưng còn 1 nguyên nhân khác, đó là máy chủ server tính toán quá nhiều dẫn đến kết quả đưa ra. Đây là điều thường thấy ở những website về Diễn Đàn (Forum), Tin Tức (Portal) và Thương mại điện tử (Ecommerce). Khi số lượng thành viên, số lượng bài viết tăng lên, đồng nghĩa với việc Database khi truy vấn (query) 1 yêu cầu phải duyệt qua tất cả các dữ liệu hiện có để tìm ra dữ liệu thích hợp. Cũng giống như 1 quyển sách. Nếu sách là mỏng, bạn dễ dàng tìm ra thông tin mình cần. Nhưng khi sách dầy lên, thời gian tìm kiếm của bạn sẽ tăng đáng kể.
Việc Database quá tải còn dẫn đến nhiều thiệt hại khác, các hàng đợi (Queuie) dài ra, file logs lớn lên chiếm hết không gian đĩa và user khi kết nối sẽ bị từ chối. Rõ ràng là câu báo lỗi “Too many connections” không phải là hiếm gặp trong các website trên Internet. Những lỗi trên thông thường bắt nguồn từ khâu định nghĩa Database (define) hay không sử dụng Indexes. Khắc phục những thiếu sót trên, Database của bạn sẽ “nhẹ nhàng” và nhanh chóng đáng kể. Hãy xem xét ví dụ sau:
CREATE TABLE tblUsers (
user_id int(11) NOT NULL,
user_name vachar(25),
user_pwd vachar(50),
user_firstname varchar(40),
user_surname varchar(40),
user_address text,
user_tel varchar(25),
user_goal int(11),
);
Và để tìm thông tin Điểm của Nguyễn Văn A (mã số 120956), bạn sẽ query như sau:
SELECT user_goal FROM tblUsers WHERE user_id = ‘120956′;
MySQL biết rằng phải tìm ở table tblUsers nhưng nó sẽ không biết bắt đầu từ đâu. Thậm chí nó cũng không biết trước rằng có bao nhiêu kết quả . Do đó nó sẽ duyệt qua tất cả danh sách (vd Hơn 300.000 người) để tìm thông tin về Nguyễn Văn A.
Index là 1 file riêng biệt được lưu trữ ở máy chủ và chỉ chứa những Fields mà bạn muốn nó chứa. Nếu bạn tạo 1 Index cho Field user_id (mã số người dùng), MySQL sẽ dễ dàng tìm ra được mã số 1 cách nhanh chóng. Trở lại ví dụ quyển sách, khi cần tìm 1 thông tin, ta thường lật ngay tới phần “Mục Lục” và tìm từ đó để tăng tốc độ tìm. Và việc tạo ra Index này sẽ làm bạn thấy Database của bạn chạy nhanh 1 cách khác thường.
Nhưng trước khi sửa lại cấu trúc của table ở trên, tôi sẽ hướng dẫn bạn 1 chút về cách theo dõi kết quả “Tăng tốc MySQL” mà bạn đang làm. Hãy sử dụng lệnh EXPLAIN
Cú pháp: EXPLAIN Query;
Bằng lệnh này bạn sẽ nhận ra được với câu Query của bạn, điều gì đang xảy ra và kiểu kết hợp (Join) nào đang diễn ra bên trong.
Xem ví dụ sau:
mysql>EXPLAIN SELECT user_id,user_firstname,user_surname FROM tblUsers WHERE user_id= ‘120956‘;
+———-+——+—————+——+———+——+——+————+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——+—————+——+———+——+——+————+
| tblUsers | ALL | NULL | NULL | NULL | NULL | 86792| where used |
+———-+——+—————+——+———+——+——+————+
Giải thích:
- table : Table nào đang liên quan đến output data
- type : Đây là thông tin quan trọng, nó cho chúng ta biết kiểu query nào nó đang sử dụng. Mức độ từ tốt nhất đến chậm nhất như sau: system, const, eq_ref, ref, range, index, all
- possible_keys : Đưa ra những Index có thể sử dụng để query
- key : và Index nào đang được sử dụng
- key_len : Chiều dài của từng mục trong Index
- ref : Cột nào đang sử dụng
- rows : Số hàng (rows) mà MySQL dự đoán phải tìm
- extra : Thông tin phụ, thật tệ nếu tại cột này là “using temporary” hay “using filesort”
Wow, nhìn lại câu query của chúng ta mới thật khủng khiếp. Không có Possible_keys nào được sử dụng, MySQL phải duyệt qua 86792 bản ghi mới tìm ra cái ta cần (Hãy tưởng tượng 1 Forum sẽ có đến hơn 500.000 bản ghi).
Bây giờ chúng ta sẽ thêm Index vào và query lại
mysql>ALTER TABLE tblUsers ADD INDEX idx_userid(user_id);
mysql>EXPLAIN SELECT user_id,user_firstname,user_surname FROM tblUsers WHERE user_id= ‘120956‘;
+———-+——-+—————+———+———+——-+——+——-+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——-+—————+———+———+——-+——+——-+
| tblUsers | const | PRIMARY | PRIMARY | 10 | const | 1 | |
+———-+——-+—————+———+———+——-+——+——-+
Tốt hơn nhiều rồi, kiểu TYPE = Const có nghĩa rằng MYSQL hiểu ra chỉ có 1 hàng đúng với ý ta, và thể hiện qua cột Rows = 1, kiểu key= PRIMARY được sử dụng và chiều dài key_len là 10.Chỉ tìm 1 hàng tất nhiên rằng tốt hơn nhiều so với tìm 86792 hàng
Vậy câu hỏi đặt ra là, nếu tôi muốn thêm Index cho những cột mà có thể có nhiều hơn 1 kết quả khi query thì sao?
Vẫn add index như bình thường,giả sử bạn cần tìm những người có họ là Nguyễn Văn, tên là A
mysql>ALTER TABLE tblUsers ADD INDEX idxSFname (user_surname, user_firstname);
mysql>EXPLAIN SELECT user_goal FROM tblUsers WHERE user_surname=’Nguyễn Văn‘ AND user_firstname=”A“;
+——–+——+——————-+———+———+——-+——+———–+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+——–+——+——————-+———+———+——-+——+———–+
|tblUsers| ref | user_surname,user_firstname | idxSFname | 41 | const | 1 |where used |
+——–+——+——————-+———+———+——-+——+———–+
Tuy nhiên, nếu chỉ cần user_firstname
mysql>EXPLAIN SELECT user_goal FROM tblUsers WHERE user_firstname=’Name’;
+———-+——+—————+——+———+——+——+————+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+———-+——+—————+——+———+——+——+————+
| tblUsers | ALL | NULL | NULL | NULL | NULL | 86792 | where used |
+———-+——+—————+——+———+——+——+————+
thì MySQL sẽ tìm hết vì không hề có Index cho user_firstname mà chỉ có Index cho (user_surname, user_firstname).
Khi nào thì cần Add Index ? Bất cứ khi nào bạn thay đổi Table bạn đều cần Add Index lại, giống như khi bạn thay đổi nội dung quyển sách, bạn cần phải làm lại mục lục. Vậy hãy cân nhắc, nếu Database của bạn sử dụng INSERT hay UPDATE nhiều hơn là SELECT thì Index chỉ làm chậm thêm mà thôi.
Có thể nhanh hơn nữa không ? Câu trả lời là Có! Bạn không cần phải làm Index cho cả Field mà chỉ cần 1 phần. Giống như chi tiết Mục Lục của sách mà quá dài cũng làm bạn khá vất vả, do đó họ chỉ trích dẫn 1 tựa đề. Quay lại với table của chúng ta, user_surname và user_firstname chỉ maximum là 40 chars, nếu chúng ta index nó, chúng ta tạo ra mỗi record đến 80 chars . Có thể tiết kiệm bằng cách sau
mysql>ALTER TABLE tblUsers ADD INDEX(user_surname(20),user_firstname(20));
Bây giờ thì bạn tiết kiệm được đến 50% mà vẫn đảm bảo được tốc độ rồi đó (trừ phi bạn làm Index quá ngắn). Có thể bạn nói đĩa cứng server tôi “vô tư” nhưng hãy nhớ rằng “Nhỏ hơn là nhanh hơn”.
ĐIỀU KÌ DIỆU VỚI OPTIMIZE VÀ ANALYZE
“Ma thuật” của MySQL là biết cách chọn khoá (key) nào để query(nếu có). Quá trình này gọi là “query optimizer”, nó sẽ “liếc” qua những Index đang có để quyết định sẽ dùng Index nào để tìm. Hãy tưởng tượng bạn đang tìm 1 dĩa CD của “Maria Carrey” có tên là “I Love You”, có nghĩa là có 2 Indexes ở đây, 1 cho tên tác giả và 1 cho tên CD. Bạn nhận thấy rằng danh mục có 20.000 tên tác giả và 400.000 tên Album. Một cách đơn giản,bạn sẽ tìm theo tên tác giả. Khi có được, bạn lại thấy rằng “Maria Carrey” có 50 CDs và CD “I Love You” bắt đầu bằng chữ I. Đơn giản và dễ dàng tìm ra cái mình muốn phải không ? MySQL cũng vậy nhưng …bạn phải chỉ cho nó bằng cách:
ANALYZE TABLE tablename;
Những lệnh DELETE và UPDATE để lại rất nhiều những khoảng trống (gaps) vô nghĩa cho table (Đặc biệt là khi bạn dùng kiểu varchar hay text/blob). Điều đó có nghĩa rằng MySQL cũng phải đọc và phân tích những thứ vô nghĩa đó khi query. Điều này được khắc phục khi bạn chạy
OPTIMIZE tablename;
Do đó 2 câu lệnh trên bạn nên chạy 1 cách thường xuyên để bảo đảm tối ưu hoá Database của mình.
webdesignviet đã test thử, bài viết rất hưu ích nên xin phép chia sẽ lại ở đây.

Javascript post on form Submit open a new window


1/ html form

form name="my_form"
Title: input type="text" name="txttitle"
Content: textarea name="txtcontent" textarea
input type="submit" name="btsubmit" value="Submit"
input type="button" name="btreview" value="Review"

2/ jquery or javascript function 

//jquery
$('#btreview').click(function(){
with(document.my_form) {
method = 'POST';
action = 'php_post.php';
target = '_blank';
submit();
}
});
//javascript funtion
function review()
{
with(document.my_form) {
method = ‘POST’;
action = ‘php_post.php’;
target = ‘_blank’;
submit();
}
}
Nếu sử dụng javascript funtion nhớ khai báo gọi hàm tại tab button

input type="button" name="btreview" value="Review" onclick="/review();/"
do blog không cho post thẻ(tag) html nên các bạn nhớ ghi thẻ cho đúng <inp…, , ..etc

JavaScript sprintf


sprintf trong javascript (giống keyword sprintf trong PHP)
1/ Download code từ link sau:
2/ Cách sử dụng:
đặt khối lệnh sau trong thẻ khai báo thực thi ngôn ngữ javascript
3/ Một vài kiểu dữ liệu
% — print a literal “%” character
b — print an integer as a binary number
c — print an integer as the character with that ASCII value
d — print an integer as a signed decimal number
e — print a float as scientific notation
u — print an integer as an unsigned decimal number
f — print a float as is
o — print an integer as an octal number
s — print a string as is
x — print an integer as a hexadecimal number (lower-case)
X — print an integer as a hexadecimal number (upper-case)

Codeigniter pdf libraries (php export pdf Unicode/UTF8 – Vietnamese)


Thêm mPDF libraries cho Codeigniter Framework, xuất file pdf Tiếng Việt có dấu (pdf Unicode/utf8)

Step 1:  Download mPDF tại địa chỉ URL: http://www.mpdf1.com/mpdf/download
Step 2:  Giải nén (uncompress) thư viện mPDF vào thư  mục libraries của Codeigniter như  sau:
your_project/system/application/libraries/mpdf/ (uncompress mpdf)
Step 3: Tạo file để gọi các lớp trong thư viện mpdf như  sau:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Codeigniter: mpdf libraries
 * Tuesday, July, 19 2011
 * 
 * @author bang.webdeveloper@gmail.com
 */
require_once dirname(__FILE__) . '/mpdf/mpdf.php';

class Pdf extends mPDF
{
 function __construct()
 {
 parent::__construct();
 }
}
?>
Sau đó lưu (Save) tại đường dẫn sau:
your_project/system/application/libraries/Mpdf.php
Step 4: Sử dụng
$html = "<b>Cho ví dụ minh họa</b>";
$this->load->library('Mpdf');
$mpdf = new Pdf();
$mpdf->useAdobeCJK = true;
$mpdf->SetAutoFont(AUTOFONT_ALL);
$mpdf->WriteHTML($html);
$save_file = $dir_bill.$filename.'.pdf';
$mpdf->Output(); //Neu xuat ra file $mpdf->Output('dir/ten_file_pdf', 'F');
author:  nhantam

popup SimpleModal hiển thị khi mở web (Web Browser Open OnLoad)


1/ Download simplemodal tại địa chỉ sau:
http://www.ericmmartin.com/projects/simplemodal/
2/ Ví dụ modal osx hiển thị khi mở web (open onload)
style modal osx hiển thi khi click vào link or button như vĩ dụ đã có sẵn từ link download trên.
Sửa file osx.js như sau:
dóng tag sau
//jQuery(function ($) {
 var OSX = {
        .........
////});
thêm đoạn code sau
jQuery(function ($) {
 $("#osx-modal-content").modal({
  overlayId: 'osx-overlay',
  containerId: 'osx-container',
  closeHTML: '<div class="close"><a href="#" class="simplemodal-close">x</a></div>',
  minHeight:80,
  opacity:65,
  position:['0',],
  overlayClose:true,
  onOpen:OSX.open,
  onClose:OSX.close
 });
});

Thứ Bảy, 26 tháng 1, 2008

XHTML


Mục lục:
1. Giới thiệu XHTML.
2. Một số khác biệt giữ XHTML & HTML.
3. Kết luận


1. Giới thiệu XHTML
1.1 XHTML là gì ?
XHTML viết tắt của tiếng Anh
Extensible HyperText Markup Language, "Ngôn ngữ đánh dấu siêu văn bản mở rộng". XHTML là một ngôn ngữ đánh dấu có cùng các khả năng như HTML, nhưng có cú pháp chặt chẽ hơn.
1.2 Tổng quát về XHTML.
Về phương diện kỹ thuật XHTML là một họ các kiểu tài liệu hiện tại & tương lai cùng các module nhằm tái tạo lại, mở rộng thâu nạp HTML, tái cấu trúc lại dưới dạng XML. Các dạng tài liệu thuộc họ XHTML tất cả đều dựa trên XML và được thiết kế để làm việc tuyệt đối với các trình đại diện người dùng hiểu XML, XHTML là thế hệ kế tiếp của HTML và đã có một loạt các đặc tả được phát triển cho XHTML.


2. Một số khác biệt giữa XHTML & HTML

2.1 Các phần tử phải được lồng nhau đúng cách.

Trong HTML các phần tử có thể được lồng vào nhau không đúng cách :
This text is bold and italic.
Trong XHTML tất cả các phần tử phải được lồng vào nhau đúng cách:
This text is bold and italic
Chú ý: Một lỗi thường thấy ở các danh sách gạch đầu dòng lồng vào nhau mà quên mất rằng danh sách bên trong phải được đặt trong phần tử li. Ví dụ:
  
  • Coffee
  •   
    
  • Tea
  •     
          
    
  • Black tea
  •       
    
  • Green tea
  •     
      
    
  • Milk
  • Phải viết lại theo chuẩn XHTML đúng:
      
    
  • Coffee
  •   
    
  • Tea
  •     
          
    
  • Black tea
  •       
    
  • Green tea
  •     
      
      
    
  • Milk


  • 2.2 Phải đặt thẻ ở dạng chuẩn

    Tất cả các phần tử XHTML phải được đặt lồng bên trong phần tử gốc . Tất cả các phần tử khác có thể có các phần tử con. Các phần tử con phải đi theo cặp và phải được đặt lồng nhau đúng cách bên trong phần tử mẹ. Cấu trúc tài liệu cơ bản là:
        ... 
        ... 


    2.3 Tên thẻ đều viết thường.

    Do XHTML kế thừa cú pháp của XML và mỗi trang XHTML đều là các ứng dụng XML cho nên XHTML có phân biệt chữ hoa chữ thường, điều không có ở HTML. Với HTML thì các thẻ như

    được hiểu là giống nhau nhưng một khi bạn đã xác định trang web của bạn là XHTML thì trình duyệt sẽ dịch hai thẻ này là khác nhau.
    HTML chấp nhận cách viết dưới:
      This is a paragraph
    
    XHTML đòi hỏi phải viết lại phần trên thành:
      This is a paragraph
    


    2.4 Tất cả các thẻ(tag) đều phải được đóng lại

    Phần tử không rỗng phải có một thẻ đóng. HTML chấp nhận cách viết dưới:
    This is a paragraph
    This is another paragraph
    XHTML đòi hỏi phải viết lại phần trên thành:
    This is a paragraph
    
    This is another paragraph

    Các phần tử rỗng hoặc là phải có th đóng hoặc là thẻ khởi đầu phải được kết thúc bằng />. HTML chấp nhận cách viết dưới:
    This is a break
    
    Here comes a horizontal rule:
    Here's an image Ucon">
    XHTML đòi hỏi phải viết lại phần trên thành:
    This is a break
    
    Here comes a horizontal rule:
    Here's an image Icon" />
    Chú ý: Để làm cho trang XHTML tương thích với các trình duyệt hiện nay thì nên đặt một khoảng trắng thêm vào trước kí tự / kiểu như
    , và




    2.5 Các giá trị thuộc tính của thẻ phải được đặt trong dấu nháy kép.

    HTML chấp nhận cách viết dưới:
    XHTML đòi hỏi phải viết lại phần trên thành:
    HTML chấp nhận cách viết dưới:
    XHTML đòi hỏi phải viết lại phần trên thành:
    3. Kết luận XHTML cũng chính là HTML, được nâng cấp & tuân theo các quy tắc viết của XML. Cấu trúc & cú pháp chặt chẽ.
    Có 3 quy tắc chính trong thiết kế chuẩn XHTML:
    - Các thẻo phải viết dưới dạng chữ thường. Tức là không viết
    mà viết
    - Có thẻ mở thì có thẻ đóng. Ví dụ như có thẻ
    thì có thẻ - Trường hợp có 1 thẻ duy nhất thì cuối thẻ phải có dấu gạch chéo slash (tự đóng) ví dụ như ,
    .