XMLCart 封裝 DOM 操作,暴露高級業務 API
<?xml version="1.0" encoding="gb2312"?>
<cart>
<total>1250.00</total>
<item id="P001">
<name>筆記本電腦</name>
<price>5000.00</price>
<quantity>1</quantity>
</item>
<item id="P002">
<name>無線滑鼠</name>
<price>150.00</price>
<quantity>5</quantity>
</item>
</cart>
<cart><total>:總金額 (冗余存儲,避免重複計算)<item>:id 屬性為主鍵,子元素可擴展
public class XMLCart {
private Document myCart; // 全局 DOM 文檔
// 輔助:字符串解析為 Document
private Document parseString(String xml) throws IOException, SAXException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(xml.getBytes("gb2312")));
}
// 輔助:計算總價
private void computeTotal() {
double total = 0;
NodeList items = myCart.getElementsByTagName("item");
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
double price = Double.parseDouble(getChildText(item, "price"));
int qty = Integer.parseInt(getChildText(item, "quantity"));
total += price * qty;
}
// 更新 total 節點
Element totalElem = (Element) myCart.getElementsByTagName("total").item(0);
totalElem.setTextContent(String.format("%.2f", total));
}
private String getChildText(Element parent, String tagName) {
NodeList nl = parent.getElementsByTagName(tagName);
return (nl.getLength() > 0) ? nl.item(0).getTextContent() : "";
}
// 1. 清空購物車
public void emptyCart() throws IOException, SAXException {
String xml = "0 ";
myCart = parseString(xml);
}
// 2. 添加商品
public void addItemToCart(String itemXml) throws IOException, SAXException {
Document itemDoc = parseString(itemXml);
NodeList itemList = itemDoc.getElementsByTagName("item");
if (itemList.getLength() == 0) return;
Node newItem = itemList.item(0).cloneNode(true); // 深克隆
if (isCartEmpty()) emptyCart();
if (!isItemExist(newItem)) {
Element cartRoot = myCart.getDocumentElement();
cartRoot.appendChild(myCart.importNode(newItem, true)); // 跨文檔導入
computeTotal();
}
}
private boolean isCartEmpty() {
return myCart == null || myCart.getDocumentElement() == null;
}
private boolean isItemExist(Node item) {
String id = item.getAttributes().getNamedItem("id").getNodeValue();
NodeList items = myCart.getElementsByTagName("item");
for (int i = 0; i < items.getLength(); i++) {
Element e = (Element) items.item(i);
if (id.equals(e.getAttribute("id"))) return true;
}
return false;
}
// 3. 刪除商品
public void removeItemFromCart(String itemId) {
NodeList items = myCart.getElementsByTagName("item");
Element cartRoot = myCart.getDocumentElement();
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
if (itemId.equals(item.getAttribute("id"))) {
cartRoot.removeChild(item);
break;
}
}
computeTotal();
}
// 4. 修改數量
public void updateQuantity(String itemId, int newQty) {
NodeList items = myCart.getElementsByTagName("item");
for (int i = 0; i < items.getLength(); i++) {
Element item = (Element) items.item(i);
if (itemId.equals(item.getAttribute("id"))) {
Element qtyElem = (Element) item.getElementsByTagName("quantity").item(0);
qtyElem.setTextContent(String.valueOf(newQty));
break;
}
}
computeTotal();
}
// 5. 獲取 XML 字符串 (供前端渲染/傳輸)
public String toXmlString() throws TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "gb2312");
StringWriter writer = new StringWriter();
transformer.transform(new DOMSource(myCart), new StreamResult(writer));
return writer.toString();
}
}
<%-- 獲取購物車 XML --%>
<%
XMLCart cart = (XMLCart) session.getAttribute("cart");
String cartXml = cart.toXmlString();
%>
<%-- 應用 XSLT 生成 HTML --%>
<discount>、<tax> 子元素,computeTotal() 擴展邏輯setValidating(true)XMLCart 非線程安全,Web 環境下存入 Session (單線程訪問) 或加鎖XML 購物車 = 結構化數據 + 標準化交換 + 多渠道渲染。Java DOM API 雖顯冗長,但標準、穩定、無依賴,是輕量級方案的不二之選。