跳轉到內容

XQuery/拆分檔案

來自華夏公益教科書,開放的書籍,開放的世界

您有一個包含許多一致記錄的大型 XML 文件。 您希望將其拆分成多個較小的文件,以便每個文件都可以由不同的使用者編輯。 拆分大型檔案有很多很好的理由。 有些與您一次要載入到編輯器中的資料量有關,或者與您如何將單個檔案釋出到遠端站點有關。

eXist 和許多其他系統都進行版本控制併為每個檔案保留日期/時間戳。 使用較小的檔案,這些功能可能更容易執行。

我們將建立一個 XQuery,它將遍歷文件中的所有記錄。 對於每條記錄,我們將使用 XQuery 函式將文件儲存在集合中。 此函式的格式為

xmldb:store($collection, $filename, $data)

其中

  • $collection 是一個字串,儲存我們將儲存每條記錄資料的集合的路徑。 例如 '/db/test/data'
  • $filename 是檔名稱。 該名稱可以從資料中推匯出來,也可以由拆分查詢中的序列計數器生成。 例如 'Hello.xml" 或 "1.xml"。
  • $data 是我們將儲存到檔案中的資料

示例輸入 XML 文件

[編輯 | 編輯原始碼]

一種入門方法是將您的資料(如商業術語)放入電子表格並將其轉換為 XML。 oXygen XML 編輯器提供了一些非常好的工具,用於將電子表格轉換為 XML 格式。 確保您將“術語”和“定義”放在第一行,並使用此行定義元素名稱。

<root>
   <row>
      <Term>Hi</Term>
      <Definition>An informal short greeting.</Definition>
   </row>
   <row>
      <Term>Hello</Term>
      <Definition>A more formal greeting.</Definition>
   </row>
</root>

示例 XQuery

[編輯 | 編輯原始碼]
xquery version "1.0";

let $input-document := '/db/test/input.xml'
let $collection := '/db/test/terms'

(: the login used must have write access to the collection :)
let $output-collection := xmldb:login($collection, 'my-login', 'my-password')

return
<SplitResults>{
     for $term-data in doc($input-document)/root/row
        (: For brevity we will create a file name with the term name.  Change this to be an ID function if you want :)
        let $term-name := $term-data/Term/text()
        let $documentname := concat($term-name, '.xml')
        let $store-return := xmldb:store($collection, $documentname, $term-data)
     return
        <store-result>
           <store>{$term-name}</store>
           <documentname>{$documentname}</documentname>
        </store-result>
}</SplitResults>

使用序列計數器生成人工鍵

[編輯 | 編輯原始碼]

有時,匯入記錄中沒有可以作為唯一鍵使用的元素,或者不適合用作人工鍵。 在這種情況下,您將需要使用計數器來建立包含唯一編號的 XML 文件。 生成的序列號稱為“人工鍵”,因為它與記錄中的任何資料元素沒有直接關係。

您可以透過在 for 迴圈中新增“at counter”來實現此目的。 為此,只需在 for 變數之後新增字串 at $count,如下所示

for $term-data at $count in $input-file/row

然後,store 函式可以使用 $count 變數來建立包含此編號的檔名

let $filename := concat($count, '.xml')

使用 XQuery 更新運算子為每個專案新增 ID

[編輯 | 編輯原始碼]

將資料插入集合後,您將需要為每個專案分配一個唯一的 ID。 由於它是透過人工匯入過程建立的,並且與專案內部的資料無關,因此這被稱為人工鍵。 人工鍵通常由儲存資料的計算機系統分配,但不是從資料中推匯出來的。

<item>
   <person-name>John Doe</person-name>
   ...
</item>

您還可以透過執行以下操作來自動為每個專案新增 ID

  for $item at $count in $items
  return
     update insert <id>{$count}</id> preceding $item/person-name

更新後,新的 ID 元素將插入 person-name 元素之前

<item>
   <id>47</id>
   <person-name>John Doe</person-name>
   ...
</item>

最佳做法是確保專案還沒有 ID 元素。

  for $item at $count in $items[not(id)]
  return
     update insert <id>{$count}</id> preceding $item/person-name

這可以防止指令碼執行兩次時新增重複的 id。 您也可以對其進行修改,使其從集合中最大 id 的下一個數字開始計數。

  (: get the largest ID in the collection :)
  let $largest-id := max(  collection($my-collection)/*/id/text() )
  let $offset := $largest-id + 1
  for $item at $count in $items[not(id)]
  return
     update insert <id>{$count + $offset}</id> preceding $item/person-name

參考資料

[編輯 | 編輯原始碼]

拆分模式記錄在企業模式整合網站上。 請注意,儘管 URL 中的名稱為“Sequencer”,但該模式稱為“Splitter”。

另外請注意,您選擇載入到客戶端的檔案大小會對併發編輯的執行方式產生很大影響。 這對需要鎖定哪些資料進行編輯有很大影響。 有關更多資訊,請參見XRX 鎖定粒度設計

華夏公益教科書