XQuery/解压缩 Office Open XML docx 文件
外观
< XQuery
您想要解压缩一个 docx 文件
我们将使用之前示例中使用的压缩:unzip() 函数,并将处理解压缩的本地版本传递给它。
docx 文件中的一些文件名,例如 '[Content_Types].xml',不是有效的 URI。因此,必须将它们重命名为具有有效 URI 的文件。
这里是一个典型的 docx 文件中的路径名列表
<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>
请注意,创建了三个子文件夹(_rels、word 和 docProps)。XML 文件存储在这些文件中。
以下函数用于解压缩 docx 文件。此函数名必须作为参数传递给 unzip 函数,以告诉它对每个 docx 文件进行何种操作。
请注意,您必须从调用函数中传递参数到此函数。
unzip-docx 函数
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)}"/>
};
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>
};
let $collection := '/db/test/'
let $zip-filename := 'hello-world.docx'
let $action := 'unzip' (: valid actions: 'list', 'unzip' :)
return
local:unzip($collection, $zip-filename, $action)