Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 转换和xmldb:store中存在数据库特殊字符_Xslt_Xquery_Exist Db - Fatal编程技术网

Xslt 转换和xmldb:store中存在数据库特殊字符

Xslt 转换和xmldb:store中存在数据库特殊字符,xslt,xquery,exist-db,Xslt,Xquery,Exist Db,我有一个关于eXist db 4.5中输出转义的问题: 我正在使用transform:transform(带有$serialization options=方法=文本媒体类型=应用程序/text)和xmldb:store(带有$mime-type=文本/plain)将XSL转换的输出保存回数据库。在我使用的xslt样式表中 <xsl:value-of select="concat('Tom ', '&amp;', ' Peter')"/> 像建议的那样使用transform

我有一个关于eXist db 4.5中输出转义的问题:

我正在使用
transform:transform
(带有
$serialization options
=
方法=文本媒体类型=应用程序/text
)和
xmldb:store
(带有
$mime-type
=
文本/plain
)将XSL转换的输出保存回数据库。在我使用的xslt样式表中

<xsl:value-of select="concat('Tom ', '&amp;', ' Peter')"/>
像建议的那样使用
transform:stream transform
也不起作用,因为我需要将输出保存到文本文件中

如何确保在XSL转换中可以使用
concat
和特殊字符,如
&


编辑:添加示例 假设您在
/db/apps/
下有一个名为
temp
的现有集合,其中包含以下文件:

input.xml

transformation.xq

当您使用select选项中包含的三个
值评估
transformation.xq
时,您会看到工作文件生成一个
*.tex
文件,其内容为
Tom&;Peter
这不是预期的(即
Tom&Peter

根据eXist的函数文档,此函数返回一个
节点()
(或一个空序列)。因此,尽管您可能会试图强制XSLT转换的结果成为一个普通的旧字符串(正如您通过提供
method=text
serialization参数所做的那样),该函数仍然会将该字符串作为一个节点(一个文本节点)返回

当您将文本节点传递给
xmldb:store()
函数以存储文本文件(在您的例子中是.tex文件)时,序列化将再次发挥作用,因为文本节点必须序列化为现有用于文本文件的二进制形式。默认的序列化方法是XML方法,它在序列化文本节点时转义字符串

要测试此假设,请运行以下查询并检查结果文件:

xmldb:store("/db", "01-text-node.txt", text { "Tom &amp; Peter" } ),
xmldb:store("/db", "02-string.txt", "Tom &amp; Peter" )
为了避免此问题并确保使用text方法存储转换后的值,您应该使用几种方法中的一种来派生文本节点的字符串值-这里我将这些方法应用于
$transform
变量:

  • 使用
    cast-as
    运算符:
    $transform cast-as-xs:string
  • 使用
    fn:string()
    函数:
    string($transform)
    $transform/string()
  • 使用
    fn:serialize()
    函数:
    serialize($transform,map{“method”:“text})

  • 更新:下面评论中报告的问题可能导致
    transform:transform()
    函数返回多个
    节点()
    ,这可能导致上述解决方案1和2导致意外的基数错误。解决方法是使用
    fn:string-join()
    函数。解决方案3无需调整即可工作。

    如果您可以发布一个最小的、自包含的、可复制的示例来演示该现象,这将非常有帮助。那可能吗?然后我们可以看看解决这个问题需要什么。嗨@joewiz,我希望我的例子足够了!的确如此!我能够重现你的问题并弄清问题的真相。当你有机会看一看,请让我知道,如果有什么在我的答案是不清楚的。谢谢!选项1和2不起作用,因为转换后我们有多个textnode;获取了类似
    的错误,参数1的实际基数与函数的signature:string($arg as item()?)xs:string中声明的基数不匹配。期望基数:0或1,得到713。
    使用
    fn:serialize()
    函数(选项3)有效,但我们最终使用了
    字符串连接($transform)
    ,这也有效!我接受你的答案,也许你可以添加第四个选项?嗯,很高兴你找到了字符串连接的解决方法,但我很困惑transform:transform的结果可能不是(零或-)一个节点。上面写的代码真的产生了这个结果吗?如果是这样,我们可能有一个未知的错误存在。任何进一步的信息,你可以提供将是有益的!
    transformation.xq
    的代码与我们在eXist中使用的代码完全相同。然而,我们的
    input.xml
    stylesheet.xsl
    显然要复杂得多;)如果对你有帮助的话,我可以把那些文件寄给你!那太好了。你能把它们写进新的一期吗?理想情况下,测试将演示
    transform:transform()
    函数返回的节点数超过1个
    node()!
    
    <?xml version="1.0" encoding="UTF-8"?>
    <testxml>
        <name>Peter</name>
    </testxml>
    
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        version="2.0">
    
        <xsl:template match="/">
        <!-- Ampersand is not encoded: --> <xsl:value-of select="concat('Tom ', '&amp; ', testxml/name)"/> -->
        <!-- transformation fails: <xsl:value-of disable-output-escaping="yes" select="concat('Tom ', '&amp;', testxml/name)"/> -->
        <!-- Doesn't work obviously: <xsl:value-of select="concat('Tom ', '&', testxml/name)"/> -->
        </xsl:template>
    
    </xsl:stylesheet>
    
    xquery version "3.1";
    
    declare function local:xml2tex() as xs:string
    {
    let $mime-type := "text/plain"
    let $stylesheet := doc("/db/apps/temp/stylesheet.xsl")
    let $serializationoptions := "method=text media-type=application/text"
    let $doc := doc("/db/apps/temp/input.xml")
    let $filename := (replace(util:document-name($doc), "\.xml$", "") || ".tex")
    let $transform := transform:transform(
        $doc,
        $stylesheet,
        (),
        (),
        $serializationoptions)
    let $store := xmldb:store("/db/apps/temp", $filename, $transform, $mime-type)
    return
    $filename
    };
    
    local:xml2tex()
    
    xmldb:store("/db", "01-text-node.txt", text { "Tom &amp; Peter" } ),
    xmldb:store("/db", "02-string.txt", "Tom &amp; Peter" )