:::

DSpace使用XMLMetadata的方法

3月 11, 2009 , 0 Comments Edit Copy Download

之前我為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的重新編譯,方法如下:

  1. 進入指令模式
  2. 移動到你的[dspace-source]/dspace/目錄
    > cd [dspace-source]/dspace/
  3. 執行ant編譯
    > mvn package
  4. 移動到你的[dspace-source]/dspace/target/dspace-[version].dir目錄
    > [dspace-source]/dspace/target/dspace-[version].dir
  5. 執行ant打包
    > ant -Dconfig=[dspace]/config/dspace.cfg update
  6. 停止你的Tomcat伺服器
    > cd [tomcat]/bin/
    > ./shutdown.sh
  7. 複製新的.war檔案到Tomcat的webpapps目錄:
    > \cp -rf [dspace]/webapps/* [tomcat]/webapps/
  8. 重新啟動Tomcat伺服器
    > cd [tomcat]/bin/
    > ./startup.sh

測試是否安裝成功

請把該檔案放到你的DSpace在Tomcat的執行位置,然後用網址開啟該檔案看看。

例如[tomcat]/webapps/jspui/裡面。你用http://localhost:8080/jspui/XMLMetadataExample.jsp開啟,如果出現錯誤訊息表示安裝失敗。


使用XMLMetadata API

示範檔案:XMLMetadataExample.jsp

  1. 先引用org.dspace.app.util.XMLMetadata。
    <%@ page import="org.dspace.app.util.XMLMetadata" %>
  2. 從資料庫或是利用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格式,最後再進行分析。
  3. 建立XMLMetadata物件,並且給予XMLMetadata的值。
    XMLMetadata xmlObj = new XMLMetadata();
    xmlObj.setXMLdoc(xmlText);
  4. 設定你要在XMLMetadata當中找尋的路徑。請以每個節點的node-title為路徑名稱,中間用「/」來隔開。例如你要找的是在「教師」、「人名」、「姓」當中的資料,那麼請如下設定你的路徑變數:
    String path = "教師/人名/姓";
    注意你的根節點他也需要一個node-title!可是偶爾還是會有忘記設定node-title的時候,當該層沒有node-title之時,可以考慮直接空下來,繼續寫下一層。例如你根節點的node-title原本應該寫「教師」但是卻忘記寫了,那麼你的路徑就要這樣設:
    String path = "/人名/姓";
  5. 接著你就可以用API的方法來取得你的資料了。以下一一介紹各種方法:
    1. 你可以取得查詢的資料,以陣列的字串或是陣列的整數來回傳:
      String[] valueAry = xmlObj.locate(path);
      int[] valueIntAry = xmlObj.locateInt(path);
    2. 你可以取得資料的數量,假如有很多位教師,可以查詢到底有幾筆教師的:
      int count = xmlObj.locateCountNode("教師");
    3. 如果你明確知道要哪一筆,那麼也可以設定偏移值,第一筆則設定0,第二筆則設定1。如果偏移直超過查詢結果的數量,則會回傳「null」:
      int offset = 1;	
      String valueSingle = xmlObj.locateSingle(path, offset);
      int valueIntSingle = xmlObj.locateIntSingle(path, offset);
    4. 你也可以用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教學


      光是為了寫這份文件就花了我一整天,好累……