eXist-db 压缩:zip 函数是不是添加 XML 声明

Posted

技术标签:

【中文标题】eXist-db 压缩:zip 函数是不是添加 XML 声明【英文标题】:Does eXist-db compression:zip function add XML declarationeXist-db 压缩:zip 函数是否添加 XML 声明 【发布时间】:2018-08-23 16:38:52 【问题描述】:

我有一个 XQuery 函数可以将一组 XML 文件转换为 html 并压缩它们。它在每个文件上运行一个 trasform 以创建 元素。

从那个函数开始:

declare function xport:make-sources( $path as xs:string)  as item()* 
  for $article in collection(xmldb:encode-uri($path))
  let $docnum := $article/article/div[@class = 'content']/@doc/string()
  return
  <entry name="concat($docnum,'.html')" type='text' method='store'>
    transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)
</entry>
 ;

给定输入,我运行 XQuery 来显示转换的结果......我看到了这个(正是我所期望的):

<entry name="LS01.html" type="text" method="store">
<html>
    <head>
        <style>
                body 
                font-family: Arial;
                
                article img 
                width:50%;
                
         ...

你会注意到这个条目,它们都没有 XML 声明。

但是现在让我们将它们放在一起并将这些条目发送到压缩。这一切都在 Web 应用程序中。完整的 XQuery 是这样的:

xquery version "3.0";
import module namespace transform = "http://exist-db.org/xquery/transform";
declare namespace xport = "http://www.xportability.com";
declare function xport:make-sources( $path as xs:string)  as item()* 
for $article in collection(xmldb:encode-uri($path))
  let $docnum := $article/article/div[@class = 'content']/@doc/string()
  return
  <entry name="concat($docnum,'.html')" type='text' method='store'>
    transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)
</entry>
 ;
let $path := request:get-parameter("path", "")
let $filename := request:get-parameter("filename", "")
let $col := xport:make-sources($path)
return
  response:stream-binary(
    xs:base64Binary(compression:zip($col,true()) ),
    'application/zip',
    $filename
)

一切正常,我得到了所有已从 XML 转换为 HTML 的文档的 ZIP 文件。

但是,当我查看 ZIP 中的实际文件时,它有这个:

<?xml version="1.0" encoding="UTF-8"?>
<html>
   <head>

XML 声明不在 ZIP 的任何条目上。它在条目列表中的任何地方都不存在(因为它不存在)。但是压缩它们的动作显然是添加声明。我看不出其他原因或方法。即使指定 omit-xml-declaration 或将 XSL 中的输出类型更改为文本或 HTML 也没有区别。这当然是因为上面显示了 zip 的条目列表,这表明在转换之后 没有声明。

ZIP 中的文件添加了 XML 声明,句号。

有什么解决方法吗?

【问题讨论】:

eXist 的哪个版本? 您可能需要在转换后显式序列化每个文档 - 设置“omit-xml-declaration=yes”。 确实,transform:transform 确实采用了第五个参数,$serialization-options。见exist-db.org/exist/apps/fundocs/view.html?uri=http://…。在 XSLT 转换期间处理序列化可能比我下面的方法更直接,后者是序列化已经转换的节点。同样的原则也适用。但是,我的方法将在调用 transform:transform 的上下文之外起作用。两者都值得一试! 【参考方案1】:

当您的 zip-bound &lt;entry&gt; 元素的内容被传递给 compression:zip() 函数时,XML 声明被隐式地引入到您的查询中。我建议使用fn:serialize() 函数显式设置序列化选项。以下是显示如何实现您描述的结果的示例代码:

xquery version "3.1";

let $node := <html><head/><body><div><h1>Hello World!</h1></div></body></html>
let $serialized := serialize($node, map  "method": "xml", "indent": true(), 
    "omit-xml-declaration": true() )
let $entries := <entry name="test.html" type="text" method="store">$serialized</entry>
let $filename := "test.zip"
return
    response:stream-binary(
        compression:zip($entries, true()),
        'application/zip',
        $filename
    )

将此查询保存到数据库中 /db/apps/my-app/test.xq 之类的位置并通过将 Web 浏览器指向 http://localhost:8080/exist/apps/my-app/test.xq 来调用它,将导致您的浏览器下载 test.zip。打开这个 zip 文件将显示一个没有 XML 声明的 test.html 文件:

<html>
    <head/>
    <body>
        <div>
            <h1>Hello World!</h1>
        </div>
    </body>
</html>

回到基础,XQuery 中是否存在 XML 声明是通过 omit-xml-declaration serialization parameter 切换的。要在整个查询中全局省略 XML 声明,您可以将这组声明放在查询的序言中:

declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method "xml";
declare option output:omit-xml-declaration "yes";

或者,当在查询的一部分中进行本地序列化时,您可以将同一组参数作为映射传递给fn:serialize 函数(上面代码示例中使用的方法):

fn:serialize($node, map  "method": "xml", "omit-xml-declaration": true()  )

(第二个选项参数也有一个 XML 语法。)

当前版本的 eXist (v4.0.0) 和最近的版本(可能从 v3.6.0 左右开始)支持上述所有选项,并且所有版本都支持更紧凑的eXist-specific serialization facility,使用exist:serialize 选项表示为由key=value 对组成的字符串:

declare option exist:serialize "method=xml omit-xml-declaration=yes";

您可以在 conf.xml configuration file 中设置 eXist 的默认序列化行为。 conf.xml 中的默认值可以用上述方法覆盖。 eXist 中不同接口的序列化行为,例如 WebDAV 或 XML-RPC,通常尊重 conf.xml 中设置的默认值,但这些默认值可以在每个接口的基础上被覆盖;例如,请参阅 eXist 的WebDAV interface 上的序列化文档。

【讨论】:

你就是奇才。我不希望它设置默认值,所以上面的存在:序列化方法会产生完美的结果。感谢您抽出宝贵时间!

以上是关于eXist-db 压缩:zip 函数是不是添加 XML 声明的主要内容,如果未能解决你的问题,请参考以下文章

winxp下写bat 打成zip压缩包的代码怎么写

怎样在jar格式的压缩包中添加文件,我每次添加文件进去,他都会提示要重新压缩成一个压缩包,而不是直

服务结构是不是适合下载和压缩

text 在eXist-db中为xquery函数生成函数签名测试的脚本

python实现zip分卷压缩与解压

RAR7-Zip在命令行下对数据进行压缩