亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

使用DOM和XSL來格式化由Java提取的數據

2019-11-18 14:29:15
字體:
來源:轉載
供稿:網友

  java可從任何JDBC兼容數據庫提取數據,將數據轉換成一個DOM對象,然后用XSL將數據格式化成需要的形式。在上一篇文章中,我們演示了如何從數據庫中程序化地提取數據?,F在,讓我們討論如何生成DOM對象,并用一個XSL樣式表來格式化數據。這樣一來,最終的輸出就可用于任何應用程序,只要你為它們提供需要的輸入。



生成DOM文檔


Java的最新版本支持JAXP xml處理,并實現了由萬維網協會(W3C)定義的DOM API。使用這些相容于JAXP的版本,只需3行代碼即可創建一個DOM文檔對象,其中用到了JAXP factory和builder方法:


DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();

我們創建一個名為resultset的根元素,并把它添加到文檔對象中


Element root = document.createElement("resultset");
document.appendChild(root);

resultset游標遍歷結果集時,在根元素中添加包含行數據的一個新元素:


Element nextRow = document.createElement("row");

列計數必須從ResultSetMetaData對象中讀?。辉诒卷椖康臄祿鞌祿崛‰A段,它必須是已經定義好的:

int columnCount = rsmd.getColumnCount();

列名要用for循環來檢索;針對每個列名,都添加一個name節點,它帶有一個子TextNode,其中包含用于一個names元素的名值:


String[] columnNames = new String[columnCount];
Element names = document.createElement("names");
for (int i = 0; i 〈 columnCount; i++){
/* the first column is 1, the second is 2, ... */
columnNames[i] = rsmd.getColumnName(i + 1);
Element nextNameNode = document.createElement("name");
Text nextName = document.createTextNode(columnNames[i]);
nextNameNode.appendChild(nextName);
names.appendChild(nextNameNode);
}

列索引從1開始,而非從0開始。讀取每個數據行時,列值都在一個for循環中作為字符串來泛化地檢索,這個for循環將讀取每一個列值:



/* Move the cursor through the data one row at a time. */
while(resultSet.next()){
/* Create an Element node for each row of data. */
Element nextRow = document.createElement("row");
if (debug) System.out.for (int i = 0; i 〈 columnCount; i++){
/* Create an Element node for each column value. */
Element nextNode = document.createElement(columnNames[i]);
/* the first column is 1, the second is 2, ... */
/* getString() will retrieve any of the basic SQL types*/
Text text = document.createTextNode(resultSet.getString(i + 1));
nextNode.appendChild(text);
nextRow.appendChild(nextNode);
}
root.appendChild(nextRow);
}

所有數據都轉換到一個DOM文檔對象中之后,連接就可關閉。DataBaseHandler永遠不需要進行文件操作。XML文檔是在內存中創建的。
一個具體的DataBaseHandler對象


使用少數幾行代碼,即可構造一個泛化的DefaultDataBaseHandler:



public class DefaultDataBaseHandler extends AbstractDataBaseHandler{

public DefaultDataBaseHandler(String urlString, String userName,
String pass
Word, String driverName){

setUrlString(urlString);
setUserName(userName);
setPassword(password);
setDriverName(driverName);
}
}

OracleDataBase處理程序稍微有點兒復雜:

public class OracleDataBaseHandler extends AbstractDataBaseHandler{

private String thinOraclePrefix = "jdbc:oracle:thin:@";
private String urlString;
private String userName;
private String password;
private String driverName = "oracle.jdbc.OracleDriver";
private String host;
private String port;
private String sid;

public OracleDataBaseHandler(String host, String sid,
String userName, String password){

this.host = host;
this.sid = sid;
/* a valid url connection string format is: "host:port:sid" */
setUrlString(thinOraclePrefix + host + ":1521:" + sid);
setUserName(userName);
setPassword(password);
}

public OracleDataBaseHandler(String host, String port, String sid,
String userName, String password){

this.host = host;
this.sid = sid;
this.port = port;
/* a valid url connection string format is: "host:port:sid" */
setUrlString(thinOraclePrefix + host + ":" + port + ":" + sid);
setUserName(userName);
setPassword(password);
}
}

ODBCDataBaseHandler區別不大,只是它處理的是數據源名稱(DSN),而非主機名稱、端口和SID。之所以要使用與Oracle數據庫有關的主機名稱、端口號和SID,是因為我們處理的是一個數據庫服務器,而不是一個數據庫文件。但是,Microsoft access關系數據庫要使用.mdb文件:

public class ODBCDataBaseHandler extends AbstractDataBaseHandler{

private String urlString;
private String userName;
private String password;
private String driverName = "sun.jdbc.odbc.JdbcOdbcDriver";
private String dsn;
private String odbcPrefix = "jdbc:odbc:";
public ODBCDataBaseHandler(String dsn, String userName, String password){
/* a valid url connection string format is: "jdbc:odbc:dsn" */
this.dsn = dsn;
setUrlString(odbcPrefix + dsn);
setUserName(userName);
setPassword(password);
setDriverName(driverName);
}
}

要了解訪問一種特定數據庫的細節,請查閱產品文檔。你需要用另一個類來調用一個具體的DataBaseHandler,并進行XSL轉換,從而將數據庫結果轉換成一種有用的替代輸出類型。
SQLMapper

SQLMapper類用一個DataBaseHandler類來完成它的數據庫工作,并用一個映射方法將文檔對象轉換成需要的輸出類型。映射方法返回一個字符串,因為原來就假定輸出由字符數據構成。另外,也可以使用一個StringBuffer。

SQLMapper需要一個SQL查詢字符串、一個輸出類型集以及一個用于執行具體工作的DataBaseHandler。它們用set方法來初始化,并用get方法來檢索:




if ((getSQL() != null)
&& (getSQL().length() 〉 0)
&& (getOutputType() != null)
&& (isValidOutputType(getOutputType()))
&& (getDataBaseHandler() != null)){
Document document = dataBaseHandler.getDocument(getSQL());

為了轉換成需要的輸出,需要在set方法中指定一個XSL樣式表。我們創建了一個Transformer對象,它只提供一個私有getTransformer方法。該方法可獲取一個默認樣式表或者指定的樣式表。如有必要,可使用Java的TransformerFactory方法來生成一個樣式表:



TransformerFactorytransformerfactory = TransformerFactory.newInstance();
transformer = transformerfactory.newTransformer(getStylesheet());

同樣只需要幾行Java代碼就可完成轉換:


Transformer transformer = getTransformer();
StringWritersw = new StringWriter();
StreamResult result = new StreamResult(sw);
if (transformer != null) {
transformer.transform(new DOMSource(document.getDocumentElement()), result);
output = sw.toString();
System.err.println("output: " + output);
}else{
System.err.println("No Transformer");
}

Transformer對象需要一個DOMSource對象。為了獲得這個對象,我們向Transformer的構造函數傳遞一個DOM文檔的根元素。

最后要由實現者設計自己的XSL樣式表。也可選用一些默認樣式表,以便將原始數據轉換成Html或者XML。下面是一個泛化的XSL樣式表,它能使用所謂的“標識轉換”(identity transformation)技術,將生成的數據轉換成一個XML文檔,并確保輸出內容相容于UTF-8標準,并具有良好的可讀性。

〈?xml version="1.0" encoding="UTF-8"?〉
〈xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"〉
〈xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /〉
〈xsl:template match="@*node()"〉
〈xsl:copy〉
〈xsl:apply-templates select="@*node()"/〉
〈/xsl:copy〉
〈/xsl:template〉
〈/xsl:stylesheet〉


下面是一個泛化的XSL樣式表,它能將生成的數據轉換成一個HTML表格:




〈?xml version="1.0" encoding="UTF-8"?〉
〈xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"〉
〈xsl:output method="html" indent="yes" /〉

〈xsl:template match="resultset"〉
〈h2 align="center"〉Default HTML Transform Result〈/h2〉
〈table border="1" align="center"〉〈xsl:apply-templates/〉〈/table〉
〈/xsl:template〉
〈xsl:template match="names"〉
〈tr〉〈xsl:apply-templates/〉〈/tr〉
〈/xsl:template〉
〈xsl:template match="name"〉
〈td〉〈xsl:apply-templates/〉〈/td〉
〈/xsl:template〉
〈xsl:template match="row"〉
〈tr〉〈xsl:apply-templates/〉〈/tr〉
〈/xsl:template〉
〈xsl:template match="*"〉
〈td〉〈xsl:apply-templates/〉〈/td〉
〈/xsl:template〉

〈/xsl:stylesheet〉

下面是一個泛化的XSL樣式表,它將生成的數據轉換成一個WML(無線標記語言)表格:


〈?xml version="1.0" encoding="UTF-8"?〉
〈xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"〉
〈xsl:output method="html" indent="yes" /〉
〈xsl:template match="resultset"〉
〈wml〉
〈card id="index" title="Default WML Transform Result"〉
〈xsl:apply-templates/〉〈/card〉
〈/wml〉
〈/xsl:template〉
〈xsl:template match="names"〉
Names: 〈xsl:apply-templates/〉
〈/xsl:template〉
〈xsl:template match="name"〉
〈i〉〈xsl:apply-templates/〉〈/i〉
〈/xsl:template〉
〈xsl:template match="row"〉
〈card〉〈xsl:apply-templates/〉〈/card〉
〈/xsl:template〉
〈xsl:template match="*"〉
〈i〉〈xsl:apply-templates/〉〈/i〉
〈/xsl:template〉

〈/xsl:stylesheet〉

下面是一個泛化的XSL樣式表,它將生成的數據轉換成以逗號分隔的一個表格(CSV表格),它可直接用Excel讀取:



〈?xml version="1.0" encoding="UTF-8"?〉
〈xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"〉
〈xsl:output method="text" indent="yes"/〉
〈xsl:template match="names"〉
〈xsl:for-each select="*"〉
〈xsl:if test="position() != last()"〉〈xsl:value-of select="."/〉,〈/xsl:if〉
〈xsl:if test="position() = last()"〉〈xsl:value-of select="."/〉〈/xsl:if〉
〈/xsl:for-each〉
〈/xsl:template〉
〈xsl:template match="row"〉
〈xsl:for-each select="*"〉
〈xsl:if test="position() != last()"〉〈xsl:value-of select="."/〉,〈/xsl:if〉
〈xsl:if test="position() = last()"〉〈xsl:value-of select="."/〉〈/xsl:if〉
〈/xsl:for-each〉
〈/xsl:template〉
〈/xsl:stylesheet〉

運用SQLMapper的一些思路


后端數據庫可以使用一個表來定義網頁用戶界面的表單元素。在一個jsp頁中,只需幾行代碼即可檢索這個表。你的Web服務器也許安裝了一個Oracle數據庫,但是沒有前端圖形用戶界面?,F在就可以定義一個GUI的元素,讓數據庫正式工作起來:


〈%@ page language="java" contentType="text/html" import="sqlmapper.*, mywebapp.* %〉
〈%@ page errorPage="errorPage.jsp" %〉
〈html〉
〈!-- getUserArea.jsp executed on 〈%= (new java.util.Date()) %〉 --〉
〈!-- @Author: Charles Bell --〉
〈!-- @Version: April 22, 2003 --〉
〈head〉
〈title〉Your company name - 〈%= dynamicTitle %〉〈/title〉
〈/head〉
〈body background="〈%= dynamicBackgroundImageFileName%〉"〉
〈%
WebAppUtilitymyWebAppUtility = new WebAppUtility();
String host = myWebAppUtility.getDatabaseHost();
String sid = myWebAppUtility.getDatabaseSID();
String userName = (String) session.getAttribute("validatedUserName");;
String password = myWebAppUtility.getDatabasePassord();
SQLMapper mapper = new SQLMapper();
DataBaseHandler dataBaseHandler=
new OracleDataBaseHandler(host, sid, userName, password);

mapper.setSQL("select * from FormDataElements");
mapper.setOutputType("html");
mapper.setDataBaseHandler(dataBaseHandler);
mapper.setXSLTranformStyleSheet("stylesheets/formdata.xsl");
out(mapper.map);
%〉
〈%@include file="footer.jsp" %〉
〈/body〉
〈/html〉

使用這些技術,只需單擊一個按鈕,JSP網頁即可彈出最新的、根據一個活動數據庫而動態生成的報表。CSV輸出可用于生成動態的Excel電子表格。XML輸出可為另一個Web應用程序提供服務,該應用程序將與它自己的后端數據庫進行通信。


小結

我們介紹了如何創建一個接口來定義DataBaseHandler的泛化行為,并用一個抽象類來實現它,以便將這個抽象類擴展成一個定制的、具體的數據庫處理程序,所有操作只需幾行Java代碼。SQLMapper類利用這種行為來透明連接一個關系數據庫,執行SQL查詢,并將數據轉換成一個DOM文檔對象。然后,通過應用一個XSL樣式表來獲取需要的輸出,從而完成一個DOM對象的轉換。隨后,輸出可由任何應用程序使用,只需采用一種有效的、易于實現的方式來提供需要的輸入。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人性生交大片免费观看嘿嘿视频| 成人免费大片黄在线播放| 成人激情视频小说免费下载| 欧美日韩成人在线观看| 久久五月天色综合| 欧美在线视频免费| 欧美日韩成人黄色| 日本精品久久久久影院| 中文字幕精品在线视频| 91精品国产综合久久男男| 中文字幕日韩在线观看| 亚洲欧美激情精品一区二区| 日韩欧美在线第一页| 欧美国产日韩xxxxx| 亚洲成人精品久久| 国产日韩欧美夫妻视频在线观看| 亚洲欧洲美洲在线综合| 欧美激情一区二区三级高清视频| 91精品国产综合久久男男| 国外成人在线视频| 日韩精品久久久久| 国产日韩欧美91| 欧美乱妇40p| 亚洲国产成人久久综合一区| 亚洲成人三级在线| 欧美日韩国产精品专区| 日韩在线免费av| 在线观看国产欧美| 国产午夜精品久久久| 久久精品电影一区二区| 亚洲亚裔videos黑人hd| 国产成人一区二区在线| 亚洲人成绝费网站色www| 8x海外华人永久免费日韩内陆视频| 欧洲亚洲妇女av| 亚洲午夜精品久久久久久性色| 91免费欧美精品| 日韩av片免费在线观看| 精品日本美女福利在线观看| 国产精品久久久久久亚洲影视| 国产97人人超碰caoprom| 亚洲欧美国产精品va在线观看| 亚洲аv电影天堂网| 亚洲成色777777女色窝| 深夜福利亚洲导航| 国产成人综合亚洲| 日本午夜精品理论片a级appf发布| 欧美日韩国产一区中文午夜| 欧美福利视频网站| 国产精品成人国产乱一区| 在线国产精品播放| 永久免费精品影视网站| 78色国产精品| 久久九九全国免费精品观看| 亚洲天堂av女优| 午夜伦理精品一区| 日韩成人中文电影| 97精品国产97久久久久久| 亚洲欧美日韩一区在线| 91精品久久久久久综合乱菊| 国产一区二区三区视频在线观看| 九九九久久久久久| 国产精欧美一区二区三区| 中文字幕视频一区二区在线有码| 亚洲视频欧美视频| 日韩有码视频在线| 国产精品久久久久av| 欧美老妇交乱视频| 日韩经典第一页| 日韩av影院在线观看| 视频在线观看一区二区| 伊人久久久久久久久久久久久| 欧美激情一区二区三区久久久| 国产精品免费视频久久久| 一区二区三区视频在线| 亚洲国产黄色片| 91精品国产综合久久香蕉922| 国内外成人免费激情在线视频网站| 欧美日韩免费一区| 91久久久久久久久久久久久| 成人av在线天堂| 欧美电影免费播放| 97视频色精品| 欧美精品日韩www.p站| 波霸ol色综合久久| 欧美整片在线观看| 中文字幕精品网| 欧美激情亚洲视频| 国产成人a亚洲精品| 久久精品视频播放| 国内成人精品一区| 欧美中文在线观看国产| 国产精品v日韩精品| 亚洲在线观看视频网站| 日韩国产欧美区| 久久国产精品久久国产精品| 欧美激情视频在线免费观看 欧美视频免费一| 久久亚洲精品网站| 国产精品一区二区av影院萌芽| 亚洲精品视频在线观看视频| 国产高清在线不卡| 狠狠久久亚洲欧美专区| 欧美亚洲另类在线| 亚洲国产天堂网精品网站| 一本色道久久88精品综合| 亚洲人成网站色ww在线| 国产精品久久网| 亚洲成年网站在线观看| 欧日韩在线观看| 国产欧美婷婷中文| 亚洲成人性视频| 中文字幕日韩在线观看| 国产欧美精品一区二区三区-老狼| 国产精品视频久久久| 亚洲免费伊人电影在线观看av| 亚洲一区二区三区四区在线播放| 日韩免费视频在线观看| 亚洲深夜福利网站| 欧美精品videos性欧美| 456国产精品| 疯狂欧美牲乱大交777| 色婷婷av一区二区三区久久| 91精品中文在线| 欧美黑人狂野猛交老妇| 亚洲精品一区在线观看香蕉| 黄色91在线观看| 一区二区三区视频在线| 91免费精品视频| 久久香蕉国产线看观看av| 91大神在线播放精品| 亚洲精品有码在线| 中文字幕精品久久久久| 日韩经典一区二区三区| 4438全国亚洲精品在线观看视频| 亚洲一区二区自拍| 国产女人精品视频| 91精品国产高清久久久久久久久| 国产欧美一区二区三区在线| 久久精品99久久久香蕉| 91色视频在线导航| 欧美日韩性视频| 最好看的2019的中文字幕视频| 中文字幕久热精品视频在线| 成人妇女免费播放久久久| 日韩色av导航| 欧美日韩免费观看中文| 色www亚洲国产张柏芝| 992tv在线成人免费观看| 色综合久综合久久综合久鬼88| 日韩中文字幕在线观看| 中文字幕亚洲欧美日韩在线不卡| 亚洲激情第一页| 91国产高清在线| 欧美国产日本在线| 欧美刺激性大交免费视频| 日韩av网站导航| 福利微拍一区二区| 91国产精品91| 91精品久久久久久久久青青| 亚洲综合在线做性| 91美女片黄在线观看游戏| 亚洲激情在线视频| 国产精品福利网站| 91在线观看免费高清完整版在线观看|