Xquery 是否存在数据库压缩:zip函数添加XML声明

Xquery 是否存在数据库压缩:zip函数添加XML声明,xquery,exist-db,Xquery,Exist Db,我有一个XQuery函数将一组XML文件转换为HTML并压缩它们。它在每个文件上运行一个transform来创建元素 从该功能开始: 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']/

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

从该功能开始:

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>
} ;
声明函数xport:make sources($path as xs:string)为item()*{
对于集合中的$article(xmldb:encodeuri($path))
让$docnum:=$article/article/div[@class='content']/@doc/string()
返回
{transform:transform($article,doc(“/db/EIDO/data/edit/xsl/doc html.xsl”),)}
} ;
给定输入,我运行XQuery只是为了显示转换的结果。。。我看到了这一点(正是我所期望的):


身体{
字体系列:Arial;
}
第条img{
宽度: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
)
xquery版本“3.0”;
导入模块命名空间转换=”http://exist-db.org/xquery/transform";
声明命名空间xport=”http://www.xportability.com";
将函数xport:make sources($path as xs:string)声明为item()*{
对于集合中的$article(xmldb:encodeuri($path))
让$docnum:=$article/article/div[@class='content']/@doc/string()
返回
{transform:transform($article,doc(“/db/EIDO/data/edit/xsl/doc html.xsl”),)}
} ;
let$path:=请求:获取参数(“path”,“”)
让$filename:=请求:获取参数(“filename”,“”)
让$col:=xport:make sources($path)
返回
响应:流二进制(
xs:base64Binary(压缩:zip($col,true()),
“应用程序/zip”,
$filename
)
一切正常,我得到一个ZIP文件,其中包含所有从XML转换为HTML的文档

但是,当我查看ZIP中的实际文件时,它有以下内容:

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

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

ZIP中的文件添加了一个XML声明句号


有什么解决方法吗?

当zip绑定的
元素的内容传递给
压缩: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
    )
回到基本原理,XQuery中XML声明的存在与否通过。要全局省略整个查询的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
函数(上面代码示例中使用的方法):

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

eXist的当前版本(v4.0.0)和最新版本(可能自v3.6.0或更高版本)支持上述所有选项,并且所有版本都使用
eXist:serialize
选项(表示为由
key=value
对组成的字符串):

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

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

eXist的哪个版本?转换后可能需要显式序列化每个文档-设置“忽略xml声明=是”。实际上,
transform:transform
使用第五个参数,
$serialization options
。看见在XSLT转换期间处理序列化可能比下面我的方法更直接,我的方法是序列化已转换的节点。同样的原则也适用。但是,我的方法将在调用
transform:transform
的上下文之外工作。两者都值得一试!你是天才。我不希望将其设置为默认值,以便上面的exist:serialize方法生成完美的结果。谢谢你抽出时间!
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($node, map { "method": "xml", "omit-xml-declaration": true() } )
declare option exist:serialize "method=xml omit-xml-declaration=yes";