eXist-db 压缩:zip 函数是否添加 XML 声明 [英] Does eXist-db compression:zip function add XML declaration

查看:26
本文介绍了eXist-db 压缩:zip 函数是否添加 XML 声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

从那个函数开始:

declare function xport:make-sources( $path as xs:string) as item()* {对于集合中的 $article(xmldb:encode-uri($path))让 $docnum := $article/article/div[@class = 'content']/@doc/string()返回<entry name="{concat($docnum,'.html')}" type='text' method='store'>{transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)}</条目>};

根据输入,我运行 XQuery 只显示转换的结果......我看到了这一点(正是我所期望的):

<头><风格>身体 {字体系列:Arial;}文章 img {宽度:50%;}...

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

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

xquery 版本3.0";导入模块命名空间转换 = "http://exist-db.org/xquery/transform";声明命名空间 xport = "http://www.xportability.com";将函数 xport:make-sources( $path as xs:string) 声明为 item()* {对于集合中的 $article(xmldb:encode-uri($path))让 $docnum := $article/article/div[@class = 'content']/@doc/string()返回<entry name="{concat($docnum,'.html')}" type='text' method='store'>{transform:transform($article, doc("/db/EIDO/data/edit/xsl/doc-html.xsl"), <parameters/>)}</条目>};让 $path := request:get-parameter("path", "")让 $filename := request:get-parameter("filename", "")让 $col := xport:make-sources($path)返回响应:流二进制(xs:base64Binary(压缩:zip($col,true())),'应用程序/zip',$文件名)

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

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

<头>

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

ZIP 中的文件添加了 XML 声明、句点.

有什么解决方法吗?

解决方案

当您的 zip 绑定 元素的内容传递给compression:zip() 函数.我建议使用 fn:serialize() 函数显式设置序列化选项.以下示例代码展示了如何实现您所描述的结果:

xquery 版本3.1";let $node := <html><head/><body><div><h1>Hello World!</h1></div></body></html>让 $serialized := serialize($node, map { "method": "xml", "indent": true(),省略 xml 声明":true() })let $entries := <entry name="test.html" type="text" method="store">{$serialized}</entry>让 $filename := "test.zip"返回响应:流二进制(压缩:zip($entries, true()),'应用程序/zip',$文件名)

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

<头/><身体><div><h1>你好世界!</h1>

</html>

回到基本原理,XQuery 中 XML 声明的存在与否通过 omit-xml-declaration 序列化参数.要在整个查询中全局省略 XML 声明,您可以将这组声明放在查询的序言中:

declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";声明选项输出:方法xml";声明选项输出:省略-xml-声明是";

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

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

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

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

declare 选项存在:serialize "method=xml omit-xml-declaration=yes";

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

I have an XQuery function to convert a group of XML files to HTML and Zip them. It runs a trasform on each file to create <entry> elements.

Starting with that function:

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>
} ;

Given the input, I run the XQuery to just show me the result of the transformation ... and I see this (exactly what I would expect):

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

You will note the this entry and all of them have no XML Declaration at all.

But now let's put it all together and send those entries to compression. This is all inside a web application. The full XQuery is this:

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
)

Everything works, I get a ZIP file of all the documents that have been transformed to HTML from the XML.

BUT, when I look at the actually file in the ZIP, it has this:

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

The XML Declaration is not on any of the entries to ZIP. It does not exist anywhere (as it couldn't) in the list of entries. But the action of zipping them apparently is adding the declaration. I see no other reason or way. Even specifying omit-xml-declaration or changing the output type in the XSL to text or HTML makes no difference. And this is of course, because the entry list to zip is shown above and that shows the declaration is not there after the transformation.

The files in the ZIP have an added XML declaration, period.

Is there some workaround?

解决方案

The XML declaration is introduced implicitly in your query when the contents of your zip-bound <entry> elements are passed to the compression:zip() function. I'd advise setting serialization options explicitly using the fn:serialize() function. Here is sample code showing how to achieve the result you describe:

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
    )

Saving this query into the database at a location like /db/apps/my-app/test.xq and calling it by pointing your web browser at http://localhost:8080/exist/apps/my-app/test.xq will cause your browser to download test.zip. Opening this zip file will reveal a test.html file absent the XML declaration:

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

Stepping back to the fundamentals, the presence or absence of the XML declaration in XQuery is toggled via the omit-xml-declaration serialization parameter. To omit the XML declaration globally for an entire query, you can place this set of declarations in the prolog of your query:

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

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

Or, when serializing locally within a portion of a query, you can pass this same set of parameters to the fn:serialize function as a map (the method used in the code sample above):

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

(There is also an XML syntax for the 2nd options parameter.)

The current version of eXist (v4.0.0) and recent versions (probably since v3.6.0 or so) support all of the options above, and all versions support a somewhat more compact eXist-specific serialization facility, using the exist:serialize option expressed as a string consisting of key=value pairs:

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

You can set eXist's default serialization behavior in your conf.xml configuration file. The defaults in conf.xml can be overridden with the methods above. Serialization behavior over different interfaces in eXist, such as WebDAV or XML-RPC, typically respect the defaults set in conf.xml, but these defaults can be overridden on a per-interface basis; for example, see the documentation on serialization over eXist's WebDAV interface.

这篇关于eXist-db 压缩:zip 函数是否添加 XML 声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆