DSpace使用XMLMetadata的方法
之前我為DSpace 1.5.1寫過一種新型態的input-type: XMLMetadata,那裡只有處理到遞交(submit)處理,這一篇則是教大家如何利用儲存在資料庫的XMLMetadata API。
我假設你已經懂得如何從DSpace裡面取出你指定的Metadata Value,如果不懂,請參考DSpace系統文件裡面的內容管理API的章節,或是參考我之前寫過如何從DSpace的API裡面取得Item的Metadata Value教學。
安裝XMLMetadata API
請把該檔案上傳到[dspace-source]/dspace-api/src/main/java/org/dspace/app/util/當中。
然後進行DSpace的重新編譯,方法如下:
- 進入指令模式
- 移動到你的[dspace-source]/dspace/目錄
> cd [dspace-source]/dspace/
- 執行ant編譯
> mvn package
- 移動到你的[dspace-source]/dspace/target/dspace-[version].dir目錄
> [dspace-source]/dspace/target/dspace-[version].dir
- 執行ant打包
> ant -Dconfig=[dspace]/config/dspace.cfg update
- 停止你的Tomcat伺服器
> cd [tomcat]/bin/
> ./shutdown.sh - 複製新的.war檔案到Tomcat的webpapps目錄:
> \cp -rf [dspace]/webapps/* [tomcat]/webapps/
- 重新啟動Tomcat伺服器
> cd [tomcat]/bin/
> ./startup.sh
測試是否安裝成功
請把該檔案放到你的DSpace在Tomcat的執行位置,然後用網址開啟該檔案看看。
例如[tomcat]/webapps/jspui/裡面。你用http://localhost:8080/jspui/XMLMetadataExample.jsp開啟,如果出現錯誤訊息表示安裝失敗。
使用XMLMetadata API
- 先引用org.dspace.app.util.XMLMetadata。
<%@ page import="org.dspace.app.util.XMLMetadata" %>
- 從資料庫或是利用DSpace的API取得XMLMetadata的值,存入字串型態的變數當中,假如是設為xmlText。(其中rs.getString()是從資料庫查詢結果取出資料的語法,實際使用的時候,請自行設計)。
※以下是JSP端的程式,請寫在<% %>之間。String xmlText = rs.getString();
假設取得的XMLMetadata值如下:<div class=\"xml-root\"><DIV class=node> <DIV class=node-type>node</DIV> <DIV class=node-title>教師</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-node</DIV> <DIV class=node-content-temp> <DIV class=node> <DIV class=node-type>node</DIV> <DIV class=node-title>人名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-node</DIV> <DIV class=node-content-temp> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>true</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaasdsdsdf </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaasdsdsdf </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>2 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>node</DIV> <DIV class=node-title>人名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-node</DIV> <DIV class=node-content-temp> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓ewrwere</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa </DIV> <DIV class=input-required>true</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>2 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>node</DIV> <DIV class=node-title>人名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-node</DIV> <DIV class=node-content-temp> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaasdsdsdf </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>黃</DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>2 </DIV> <DIV class=input-values>2 </DIV> <DIV class=input-values>2 </DIV> <DIV class=input-values>2 </DIV></DIV></DIV> <DIV class=node-contents> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>姓</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>aaaaa2 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>aaaaa2 </DIV></DIV> <DIV class=node> <DIV class=node-type>input</DIV> <DIV class=node-title>名</DIV> <DIV class=node-repeatable>true</DIV> <DIV class=node-class>table-input</DIV> <DIV class=input-default-value>1 </DIV> <DIV class=input-required>false</DIV> <DIV class=input-type>onebox</DIV> <DIV class=input-values>1 </DIV> <DIV class=input-values>1 </DIV> <DIV class=input-values>1 </DIV></DIV></DIV></DIV></DIV></DIV> </div>
※你可能注意到了上面的XMLMetadata並不是正規的XML:他缺少了開頭的宣告,而屬性class的值也沒有正確的雙引號。這是使用IE瀏覽器在控制input-type的XMLMetadata時最後必然的結果。所以本XMLMetadata API在設計時已經考慮到這點,這些不正規的Metadata資料會被重新整理成正規的XML格式,最後再進行分析。 - 建立XMLMetadata物件,並且給予XMLMetadata的值。
XMLMetadata xmlObj = new XMLMetadata(); xmlObj.setXMLdoc(xmlText);
- 設定你要在XMLMetadata當中找尋的路徑。請以每個節點的node-title為路徑名稱,中間用「/」來隔開。例如你要找的是在「教師」、「人名」、「姓」當中的資料,那麼請如下設定你的路徑變數:
String path = "教師/人名/姓";
注意你的根節點他也需要一個node-title!可是偶爾還是會有忘記設定node-title的時候,當該層沒有node-title之時,可以考慮直接空下來,繼續寫下一層。例如你根節點的node-title原本應該寫「教師」但是卻忘記寫了,那麼你的路徑就要這樣設:String path = "/人名/姓";
- 接著你就可以用API的方法來取得你的資料了。以下一一介紹各種方法:
- 你可以取得查詢的資料,以陣列的字串或是陣列的整數來回傳:
String[] valueAry = xmlObj.locate(path); int[] valueIntAry = xmlObj.locateInt(path);
- 你可以取得資料的數量,假如有很多位教師,可以查詢到底有幾筆教師的:
int count = xmlObj.locateCountNode("教師");
- 如果你明確知道要哪一筆,那麼也可以設定偏移值,第一筆則設定0,第二筆則設定1。如果偏移直超過查詢結果的數量,則會回傳「null」:
int offset = 1; String valueSingle = xmlObj.locateSingle(path, offset); int valueIntSingle = xmlObj.locateIntSingle(path, offset);
- 你也可以用XPath上來找尋資料:
String[] valueAry = xmlObj.locateXPath(XPath);
- 你可以取得查詢的資料,以陣列的字串或是陣列的整數來回傳:
善用XPath來作更進一步的查詢
聰明的你也許發現到前面locate所用的路徑查詢語法並不是正確的XPath查詢語法,而是我為簡化查詢XMLMetadata而設計的方法。
舉例來說,剛剛查詢「教師/人名/姓」的語法,利用XPath查詢XMLMetadata則會非常地複雜。你可以利用public String titlePathToXPath(String titlePath)來看一下XMLMetadata的路徑是怎麼轉換成完整的XPath:
String path = "教師/人名/姓"; String XPath = "/div[@class='xml-root']/DIV[@class='node'][DIV[@class='node-title']/text() ='教師']/DIV[@class='node-contents']/DIV[@class='node'][DIV[@class='node- title']/text()='人名']/DIV[@class='node-contents']/DIV[@class='node'][DIV [@class='node-title']/text()='名']/DIV[@class='input-values']/text()"; out.print(xmlObj.titlePathToXPath(path)); //Show full XPath
因為時間不多,XMLMetadata的查詢語法並不是很完整。如果你需要更完整的查詢功能,那麼你得需要自行撰寫XPath才行。
詳細的XPath教學,可以參考w3schools.com的XPath教學。
光是為了寫這份文件就花了我一整天,好累……