JSP XML 資料處理完整指南
掌握 JSP 處理 XML 資料的完整技術棧:XML 內容輸出、JSTL XML 標籤庫解析查詢、XSLT 樣式表轉換、RSS/Atom 摘要產生與實際應用場景。
JSP 輸出 XML 內容
設定 Content-Type
<%@ page contentType="text/xml; charset=UTF-8" %>
直接輸出 XML 範例
<%@ page contentType="text/xml; charset=UTF-8" %>
<books>
<book>
<name>Padam History</name>
<author>ZARA</author>
<price>100</price>
</book>
</books>
動態產生 XML (搭配資料庫)
<%@ page contentType="text/xml; charset=UTF-8"
import="java.sql.*,java.util.*,com.example.model.*" %>
<%
// 假設從資料庫查詢書籍清單
List<Book> books = BookDAO.getAllBooks();
%>
<books>
<% for (Book book : books) { %>
<book id="<%= book.getId() %>">
<name><%= book.getName() %></name>
<author><%= book.getAuthor() %></author>
<price><%= book.getPrice() %></price>
</book>
<% } %>
</books>
JSTL XML 標籤庫 - 解析與查詢
必要庫檔 (放入 Tomcat lib 目錄)
XercesImpl.jar - XML 解析器
xalan.jar - XSLT 處理器
引入標籤庫
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="https://java.sun.com/jsp/jstl/xml" %>
books.xml 資料來源
<books>
<book>
<name>Padam History</name>
<author>ZARA</author>
<price>100</price>
</book>
<book>
<name>Great Mystery</name>
<author>NUHA</author>
<price>2000</price>
</book>
</books>
main.jsp - XML 解析與 XPath 查詢
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="https://java.sun.com/jsp/jstl/xml" %>
<html><head><title>JSTL XML 解析</title></head><body>
<h3>書籍資訊:</h3>
<!-- 匯入 XML 資源 -->
<c:import var="bookInfo" url="https://localhost:8080/books.xml"/>
<!-- 解析 XML 文檔 -->
<x:parse xml="${bookInfo}" var="output"/>
<!-- XPath 查詢 -->
<b>第一本書標題:</b>
<x:out select="$output/books/book[1]/name" /><br/>
<b>第二本書價格:</b>
<x:out select="$output/books/book[2]/price" />
</body></html>
執行結果
書籍資訊:
第一本書標題:Padam History
第二本書價格:2000
核心 XML 標籤對照
| 標籤 | 用途 | 關鍵屬性 |
| <x:parse> | 解析 XML 字串/文檔 | xml (來源)、var (結果變數)、scope |
| <x:out> | 輸出 XPath 查詢結果 | select (XPath 運算式)、escapeXml |
| <x:set> | 設定 XPath 節點值 | select、var、scope |
| <x:if> | XPath 條件判斷 | select (布林運算式) |
| <x:choose/when/otherwise> | 多重 XPath 條件 | select |
| <x:forEach> | 迭代 XPath 節點集合 | select、var、varStatus |
| <x:transform> | XSLT 轉換 | xml、xslt、doc、result |
| <x:param> | XSLT 參數傳遞 | name、value |
迭代輸出所有書籍
<x:forEach var="book" select="$output/books/book">
<p>書名:<x:out select="$book/name"/></p>
<p>作者:<x:out select="$book/author"/></p>
<p>價格:<x:out select="$book/price"/></p>
<hr/>
</x:forEach>
XSLT 樣式表轉換
style.xsl - XSLT 樣式表
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="https://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html><body>
<xsl:apply-templates/>
</body></html>
</xsl:template>
<xsl:template match="books">
<table border="1" width="100%">
<tr><th>書名</th><th>作者</th><th>價格</th></tr>
<xsl:for-each select="book">
<tr>
<td><i><xsl:value-of select="name"/></i></td>
<td><xsl:value-of select="author"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
main.jsp - XSLT 轉換
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="https://java.sun.com/jsp/jstl/xml" %>
<html><head><title>XSLT 轉換</title></head><body>
<h3>書籍資訊 (XSLT):</h3>
<c:set var="xmltext">
<books>
<book><name>Padam History</name><author>ZARA</author><price>100</price></book>
<book><name>Great Mystery</name><author>NUHA</author><price>2000</price></book>
</books>
</c:set>
<c:import url="https://localhost:8080/style.xsl" var="xslt"/>
<x:transform xml="${xmltext}" xslt="${xslt}"/>
</body></html>
輸出結果

RSS/Atom 摘要產生實戰
RSS 2.0 範本
<%@ page contentType="application/rss+xml; charset=UTF-8" %>
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="https://java.sun.com/jsp/jstl/functions" %>
<rss version="2.0">
<channel>
<title><%= siteName %></title>
<link><%= siteUrl %></link>
<description><%= siteDescription %></description>
<language>zh-TW</language>
<lastBuildDate><%= new java.text.SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US).format(new Date()) %></lastBuildDate>
<c:forEach var="article" items="${articles}">
<item>
<title><![CDATA[${article.title}]]></title>
<link>${article.url}</link>
<description><![CDATA[${fn:escapeXml(article.summary)}]]></description>
<pubDate><%= new java.text.SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US).format(article.publishDate) %></pubDate>
<guid isPermaLink="true">${article.url}</guid>
</item>
</c:forEach>
</channel>
</rss>
XML 命名空間處理
命名空間 XML 範例
<books xmlns:bk="https://example.com/book">
<bk:book>
<bk:name>Title</bk:name>
<bk:author>Author</bk:author>
</bk:book>
</books>
JSTL XPath 命名空間前綴
<x:parse xml="${xml}" var="doc" scope="request"/>
<!-- 註冊命名空間前綴 -->
<x:set var="ns" select="namespace-uri(/books)"/>
<!-- 查詢使用前綴 -->
<x:out select="$doc/bk:books/bk:book[1]/bk:name" xmlns:bk="https://example.com/book"/>
效能與最佳實務
大型 XML 處理策略
| 策略 | 適用場景 | 工具/技術 |
| DOM 解析 (JSTL x:parse) | 小型文檔 (< 1MB)、需隨機存取 | JSTL、JDOM、DOM4J |
| SAX 事件驅動 | 大型文檔、串流處理、低記憶體 | SAXParser、StAX |
| StAX 拉取解析 | 大型文檔、雙向游標控制 | XMLStreamReader、XMLStreamWriter |
| XPath 編譯快取 | 重複查詢相同路徑 | XPathFactory、XPathExpression |
安全性考量
- XXE 防護:關閉 DTD 處理、外部實體解析
- XML 炸彈防護:限制實體擴展深度、實體數量、文檔大小
- 輸入驗證:Schema 驗證 (XSD)、白名單元素/屬性
// DocumentBuilderFactory XXE 防護設定
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("https://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("https://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("https://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
常見問題排除
| 問題 | 原因 | 解決 |
| x:parse 失敗 | XML 格式錯誤、編碼不符、XXE 限制 | 驗證 XML 格式、確認 UTF-8、檢查解析器設定 |
| XPath 查無結果 | 路徑錯誤、命名空間未處理、大小寫敏感 | 使用 //book 而非 /books/book、註冊命名空間 |
| XSLT 轉換無輸出 | template match 不符、output method 錯誤 | 檢查 match 路徑、確認 xsl:output method |
| 中文亂碼 | 編碼不一致、contentType 缺 charset | 統一 UTF-8、page contentType 加 charset |