Select dữ liệu từ database ra SiteMapNode

Trong bài viết Xây dựng Menu đa cấp với Multi Sitemap mình có hướng dẫn cách tạo menu đa cấp với MultiSitemap với dữ liệu từ file.sitemap có sẵn. Bài này mình sẽ viết hàm trong SQL để lấy dữ liệu từ database dưới dạng SiteMapNode để sử dụng tạo menu đa cấp

Thường việc này bạn có thể dùng code asp.net (C# hay VB) để thực hiện bằng vòng lặp hoặc sử dụng System.Xml - XmlTextWriter để thực hiện. Nhưng bạn cũng có thể sử dụng vòng lặp trong SQL để thực hiện việc này. Ở đây mình viết hàm trong SQL kết quả trả về là nội dung của file MenuTop.sitemap. Hàm này lấy đến menu cấp 3. nếu dự án của bạn có nhiều hơn 3 cấp bạn hãy sửa lại hàm cho phù hợp

Bạn chạy hàm sau trong SQL

-- =============================================
-- Author:        webmaster@hmweb.com.vn
-- Description:   <Get Sitemap content>
-- =============================================
ALTER   FUNCTION [dbo].[fuGetTreeNodeMap]
(
)
RETURNS NVarChar(4000)
AS 
BEGIN
DECLARE @SQL nvarchar(4000)
SET @SQL=''
-- Khai báo mở sitemap
SET @SQL=@SQL+N'<?xml version="1.0" encoding="utf-8" ?>
<siteMap>'
-- Duyệt cây cấp 1 (Có Decen=0)
DECLARE @CateID int, @CateName nvarchar(200), @Link nvarchar(200)
Declare CursorCategory Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=0
Open CursorCategory
Fetch next from CursorCategory INTO @CateID, @CateName , @Link
while @@FetchStatus =0
BEGIN
-- Nếu cây cấp 1 không có con thì đóng luôn TreeNode
IF dbo.fuCountSubMenu(@CateID)=0
BEGIN
      SET @SQL=@SQL+ '
      <siteMapNode url="'+dbo.ufDomainName() + @Link + '" title="' + @CateName + '" />'
END
-- Nếu cây cấp 1 có con thì mở TreeNote và tiếp tục duyệt cây cấp 2
      ELSE
      BEGIN
            SET @SQL=@SQL+ '
            <siteMapNode url="'+dbo.ufDomainName() + @Link + '" title="' + @CateName + '" >'
            -- Duyệt cây cấp 2
                  DECLARE @CateID2 int, @CateName2 nvarchar(200), @Link2 nvarchar(200)
                  Declare CursorCategory2 Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=1 AND  ParentID=@CateID
                  Open CursorCategory2
                  Fetch next from CursorCategory2 INTO @CateID2, @CateName2 , @Link2
                  WHILE @@FETCHSTATUS=0
                  BEGIN
                        -- Nếu cây cấp 2 không có con thì đóng luôn TreeNode
                        IF dbo.fuCountSubMenu(@CateID2)=0
                              BEGIN
                                    SET @SQL=@SQL+ '<siteMapNode url="'+dbo.ufDomainName() + @Link2 + '" title="' + @CateName2 + '" />'
                              END
                        -- Nếu cây cấp 2 có con thì mở TreeNode và tiếp tục duyệt cây cấp 3
                        ELSE
                              BEGIN
                              SET @SQL=@SQL+ '
                                    <siteMapNode url="'+dbo.ufDomainName() + @Link2 + '" title="' + @CateName2 + '" >'
                                    -- Duyệt cây cấp 3
                                    DECLARE @CateID3 int, @CateName3 nvarchar(200), @Link3 nvarchar(200)
                                    Declare CursorCategory3 Cursor For SELECT CateID, CateName, Link FROM TBCategory WHERE Decen=2 AND ParentID=@CateID2
                                    Open CursorCategory3
                                    Fetch next from CursorCategory3 INTO @CateID3, @CateName3 , @Link3
                                    WHILE @@FETCHSTATUS=0
                                          BEGIN
                                                SET @SQL=@SQL+ '
                                                <siteMapNode url="'+dbo.ufDomainName() + @Link3 + '" title="' + @CateName3 + '" />'
                                          FETCH NEXT FROM CursorCategory3 INTO @CateID3, @CateName3 , @Link3
                                          END
                                    Close CursorCategory3
                                    DEALLOCATE CursorCategory3
                                    SET @SQL=@SQL+ '</siteMapNode>'
                              END
                        FETCH NEXT FROM CursorCategory2 INTO @CateID2, @CateName2 , @Link2
                  END
                  Close CursorCategory2
                  DEALLOCATE CursorCategory2
                  SET @SQL=@SQL+ '</siteMapNode>'
            END
FETCH NEXT FROM CursorCategory INTO @CateID, @CateName , @Link
END
Close CursorCategory
DEALLOCATE CursorCategory
--Đóng sitemap
SET @SQL=@SQL+'
</siteMap>'
-- Print @SQL
RETURN  @SQL
END

Nếu bảng TBCategory của bạn có nhiều bản ghi thì độ dài chuỗi @SQL có thể quá 4000. Khi đó bạn cần phân tách và ghép chuỗi lại

Kết quả hàm trên (hoặc bạn thử bằng lệnh Print @SQL) như sau (Bạn có thể copy vào visual studio để xem đúng cấu trúc)

<?xml version="1.0" encoding="utf-8" ?>
<siteMap>
  <siteMapNode url="http://www.hmweb.com.vn" title="Thể thao" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Pháp luật" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Môi trường" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Thể thao" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá" >
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá trong nước" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá Anh" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá TBN" />
      <siteMapNode url="http://www.hmweb.com.vn" title="Bóng đá Ý" />
    </siteMapNode>
    <siteMapNode url="http://www.hmweb.com.vn" title="Quần vợt" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Sức khỏe" />
  <siteMapNode url="http://www.hmweb.com.vn" title="Kinh doanh" >
    <siteMapNode url="http://www.hmweb.com.vn" title="Chứng khoán" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Thị trường" />
    <siteMapNode url="http://www.hmweb.com.vn" title="Doanh nghiệp" />
  </siteMapNode>
  <siteMapNode url="http://www.hmweb.com.vn" title="Giải trí" />
</siteMap>

Khi đã có dữ liệu hàm trên rồi bạn có thể chạy thử bằng câu lệnh SELECT dbo.fuGetTreeNode_Map() để xem kết quả.
Từ kết quả trên để đưa ra file.sitemap bạn chỉ cần viết 1 hàm (C#) write ra file với phát biểu Select là xong.

Có thời gian mình sẽ hướng dẫn dùng asp.net để bind dữ liệu thàng sitemap

Chúc các bạn thành công