Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

XQuery/Unzipping an Office Open XML docx file

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Motivation You want to uncompress an docx file Method We will use the compression:unzip() function used in the prior example and pass it a local version of the function that handles the uncompression. File Names Some file names in docx files such as '[Content_Types].xml' are not valid URIs. So these must be renamed to files with valid URIs. Here is a typical list of the path names in a docx file: <item path="[Content_Types].xml" type="resource">Types</item> <item path="_rels/.rels" type="resource">Relationships</item> <item path="word/_rels/document.xml.rels" type="resource">Relationships</item> <item path="word/document.xml" type="resource">w:document</item> <item path="word/theme/theme1.xml" type="resource">a:theme</item> <item path="word/settings.xml" type="resource">w:settings</item> <item path="word/fontTable.xml" type="resource">w:fonts</item> <item path="word/webSettings.xml" type="resource">w:webSettings</item> <item path="docProps/app.xml" type="resource">Properties</item> <item path="docProps/core.xml" type="resource">cp:coreProperties</item> <item path="word/styles.xml" type="resource">w:styles</item> Note that there are three subfolders created (_rels, word and docProps). The XML files are stored in these files. unzip-docx function The following function is used to unzip a docx file. This function name must be passed as a parameter to the unzip function to tell it to do with each docx file. Note that you must pass in parameters to this function from the calling function. unzip-docx function: declare function local:unzip-docx($path as xs:string, $data-type as xs:string, $data as item()?, $param as item()*) { if ($param[@name eq 'list']/@value eq 'true') then <item path="{$path}" data-type="{$data-type}"/> else let $base-collection := $param[@name="base-collection"]/@value/string() let $zip-collection := concat( functx:substring-before-last($param[@name="zip-filename"]/@value, '.'), '_', functx:substring-after-last($param[@name="zip-filename"]/@value, '.') , '_parts/' ) let $inner-collection := functx:substring-before-last($path, '/') let $filename := if (contains($path, '/')) then functx:substring-after-last($path, '/') else $path (: we need to encode the filename to account for filenames with illegal characters like [Content_Types].xml :) let $filename := xmldb:encode($filename) let $target-collection := concat($base-collection, $zip-collection, $inner-collection) let $mkdir := if (xmldb:collection-available($target-collection)) then () else xmldb:create-collection($base-collection, concat($zip-collection, $inner-collection)) let $store := (: ensure mimetype is set properly for .docx rels files :) if (ends-with($filename, '.rels')) then xmldb:store($target-collection, $filename, $data, 'application/xml') else xmldb:store($target-collection, $filename, $data) return <result object="{$path}" destination="{concat($target-collection, '/', $filename)}"/> }; unzip function declare function local:unzip($base-collection as xs:string, $zip-filename as xs:string, $action as xs:string) { if (not($action = ('list', 'unzip'))) then <error>Invalid action</error> else let $file := util:binary-doc(concat($base-collection, $zip-filename)) let $entry-filter := util:function(QName("local", "local:unzip-entry-filter"), 3) let $entry-filter-params := () let $entry-data := util:function(QName("local", "local:unzip-docx"), 4) let $entry-data-params := ( if ($action eq 'list') then <param name="list" value="true"/> else (), <param name="base-collection" value="{$base-collection}"/>, <param name="zip-filename" value="{$zip-filename}"/> ) let $login := xmldb:login('/db', 'admin', '') (: recursion :) let $unzip := compression:unzip($file, $entry-filter, $entry-filter-params, $entry-data, $entry-data-params) return <results action="{$action}">{$unzip}</results> }; Sample Driver let $collection := '/db/test/' let $zip-filename := 'hello-world.docx' let $action := 'unzip' (: valid actions: 'list', 'unzip' :) return local:unzip($collection, $zip-filename, $action)