使用 XQuery 获取 XML 文件的文件名

Posted

技术标签:

【中文标题】使用 XQuery 获取 XML 文件的文件名【英文标题】:Getting filename of an XML file with XQuery 【发布时间】:2011-09-17 04:36:51 【问题描述】:

我将我的实体存储在 eXist XML 数据库中,并使用文件名(资源 ID)作为实体的 ID。

例子:

String xquery = "for $movie in collection('/db/movie')//movie "
    + "return $movie";

执行此查询后,我检索org.xmldb.api.base.Resource 实例,我使用其内容创建实体。当我想设置这个实体的 id 时,我会这样做:

dvd.setId(rs.getId());

问题是,如果我执行这样的查询:

String xquery = "for $dvd in collection('/db/dvd')//dvd "
        + "return <dvd>"
        + "$dvd/title"
        + "$dvd/type"
        + ""
        + "<content>"
        + " "
        + " for $movie in $dvd/content//movie"
            + "     let $movieIn := doc(concat(\"/db/movie/\", $movie/@id))/movie"
        + "     return "
            + "                    <movie id=\"$movie/@id\">"
            + "                          $movieIn/name"
            + "                          $movieIn/director"
            + "                          $movieIn/year"
            + "                          $movieIn/country"
            + "                          $movieIn/actors"
            + "                          $movieIn/genres"
            + "                    </movie>"
        + " "
        + "</content>"
        + ""
        + "</dvd>";

rs.getId() 返回null。我还尝试了来自this class 的方法getDocumentId(),但它也返回null。有没有办法让它返回资源的ID(这是实体存储的文件的名称)?

如果不可能,有没有办法(函数或其他东西)通过 XQuery 查询获取我正在使用的文件的文件名(我的意思是,数据库从中检索数据)?

我尝试替换这一行:

+ "return <dvd>"

用这个:

+ "return <dvd id=\"$dvd\">"

(以便我可以从属性中获取文件名)但它不返回文件名。

【问题讨论】:

【参考方案1】:

由于您使用的是 eXist-db,您可以使用 util:document-name() 函数:

util:document-name($dvd)

【讨论】:

【参考方案2】:

您可能正在寻找fn:base-uri()。见here。

【讨论】:

谢谢!伟大的。但是如果有一些东西只返回文件名(不是整个 uri),请告诉我。 你可以做类似fn:substring-after(fn:base-uri($dvd),fn:static-base-uri())的事情。或者另一个替换为fn:replace()。我不知道直接执行此操作的函数。 我使用 fn:substring(fn:base-uri($dvd), 9) (因为我知道 uri 的长度始终相同)但感谢您的想法! 我建议改用document-uri( root( $dvd ) ),它返回(如该页面上所述)相同,但它可以防止存在时基本属性的潜在问题......【参考方案3】:

fn:base-uri 将返回整个 URI,而不是 URI 的最后一部分,但您可以将正则表达式解决方案与 fn:base-uri 函数结合使用,以获得不依赖于 eXist 特定函数的解决方案。

这个特殊的正则表达式用 \.\w+$ 修剪扩展名,并在捕获组 2 中捕获不带扩展名的文件名

declare namespace db="http://basex.org/modules/db";
declare namespace file="http://expath.org/ns/file";
declare variable $path as xs:string external;

let $docs := collection($path)
for $doc in $docs
return
let $file := replace(fn:base-uri($doc),'^(.*/)(.*?)\.\w+$','$2')
return db:replace('13F', $file, $doc)

或者对于带有扩展名的整个文件名

  let $file := replace(fn:base-uri($doc),'^(.*/)(.*?\.\w+$)','$2')

【讨论】:

是的,第一个答案实际上并没有提供仅获取文件名的方法,而是获取整个文件路径或 uri。这真的不是在回答问题。 [xqueryfunctions.com/xq/fn_base-uri.html] 第二个是exist-db 特定的。这个适用于basexdb。我在 cmets 中读到了这个“但如果有一些东西只返回文件的名称(不是整个 uri),请告诉我”我认为这是被问到的,但不是。 我已经编辑了您的答案,将您评论的重要部分包含在其中,因为它对于只是扫描答案的人非常有用。我看到 OP 接受了 fn:base-uri 答案,并认为它完成了 OP 想要的一切。我现在看到 cmets 另有说明。如您所见,人们会跳过 cmets。 return let $file := 在 eXist 2.2 中是无效语法,并且您的正则表达式不适用于没有扩展名的文件(这很有可能)。 谢谢路易斯,是的,我没有把完整的代码放在那里。我刚刚放了一些部分代码来主要显示正则表达式。那里的代码现在可以在 basex 中使用。它将一组 xml 文档保存在 basex 中,由文件名命名,不带扩展名。我没有在 existsdb 上测试过,但 db:replace 是一个 basex 函数,我相信因此需要在 existsdb 上进行调整。

以上是关于使用 XQuery 获取 XML 文件的文件名的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Saxon 的 XQuery 中动态引用 XML 文件

xquery 随机选择文件而不重复选择

eXist DB & XQuery:带有属性的 xml-root 导致没有结果

无法解析javax.xml.xquery.XQException

XQuery 如何使用 WHERE 查询获取整个 xml 文档

使用XQuery / Xpath检测xml:id序列中的间隙/第一个ID