You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取集合中已处理XML文件的文件名?

解决方案:在XSLT 3.0批量处理中全局获取当前文件名

针对你遇到的问题,有两种可靠的方法可以让所有模板都能获取当前处理的文件名,以下是具体实现:

方法一:使用隧道参数(推荐)

隧道参数是XSLT 2.0+的特性,能在模板调用链中自动传递参数,无需在每个<xsl:apply-templates>中显式声明,非常适合需要全局共享数据的场景。

修改后的代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="3.0"
                expand-text="true">
   <xsl:mode on-no-match="shallow-skip"/>
   <xsl:output method="text" encoding="UTF-8"/>
   
   <xsl:param name="files" select="uri-collection('file:///C:/Tmp/ProjectA')"/>
   
   <xsl:template match="/">
      <xsl:result-document href="out.txt" method="text">
         <xsl:for-each select="$files">
             <!-- 提前提取当前文件的文件名 -->
             <xsl:variable name="file-name" select="tokenize(., '/')[last()]"/>
             <!-- 传递隧道参数给后续所有模板 -->
             <xsl:apply-templates select="doc(.)/root">
                 <xsl:with-param name="current-file" select="$file-name" tunnel="yes"/>
             </xsl:apply-templates>
         </xsl:for-each>
      </xsl:result-document>
   </xsl:template>
   
   <!-- 业务规则验证模板,接收隧道参数 -->
   <xsl:template match="list[not(ancestor-or-self::descr)]">
      <xsl:param name="current-file" tunnel="yes"/>
      <!-- 直接使用传递过来的文件名 -->
      <xsl:value-of select="$current-file"/>
      <xsl:text>&#10;</xsl:text>
      <xsl:text>Lists not allowed unless in descr.</xsl:text>
      <xsl:text>&#10;</xsl:text>
      <xsl:text>------------------------------------------------</xsl:text>
      <xsl:text>&#10;</xsl:text>
      <xsl:apply-templates select="node()|@*"/>
   </xsl:template>
   
   <!-- 其他需要文件名的模板,只需添加同名隧道参数即可 -->
   <xsl:template match="another-violating-node">
      <xsl:param name="current-file" tunnel="yes"/>
      <!-- 使用$current-file输出文件名 -->
      ...
   </xsl:template>
</xsl:stylesheet>

关键说明

  • 在遍历文件时提前提取文件名,避免重复计算
  • 通过tunnel="yes"标记参数为隧道参数,它会自动传递给所有后续调用的模板,无需在每个<xsl:apply-templates>中重复传递
  • 任何需要使用文件名的模板,只需添加<xsl:param name="current-file" tunnel="yes"/>即可直接使用

方法二:直接从节点获取文档URI

如果不想使用参数,可以通过当前节点的根文档节点获取原文件的URI,再提取文件名。这种方法无需修改主模板,只需在需要的模板中添加以下逻辑:

修改后的业务规则模板

<xsl:template match="list[not(ancestor-or-self::descr)]">
   <!-- 获取当前节点所在文档的URI,再提取文件名 -->
   <xsl:variable name="doc-uri" select="document-uri(root(.))"/>
   <xsl:value-of select="tokenize($doc-uri, '/')[last()]"/>
   <xsl:text>&#10;</xsl:text>
   <xsl:text>Lists not allowed unless in descr.</xsl:text>
   <xsl:text>&#10;</xsl:text>
   <xsl:text>------------------------------------------------</xsl:text>
   <xsl:text>&#10;</xsl:text>
   <xsl:apply-templates select="node()|@*"/>
</xsl:template>

关键说明

  • root(.)会获取当前节点所属的根文档节点
  • document-uri()返回该文档的原始URI,通过tokenize提取最后一段即为文件名
  • 缺点是每个需要文件名的模板都要重复编写这段逻辑,适合模板数量较少的场景

注意事项

  • 确保使用的XSLT处理器支持XSLT 3.0(如Saxon HE/PE/EE),uri-collection是XSLT 3.0的特性
  • 如果处理的文件路径包含反斜杠(Windows路径),可以用tokenize($doc-uri, '[/\\]')来兼容正反斜杠

内容的提问来源于stack exchange,提问作者Zug_Bug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:45:45