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

Saxon XSLT集合处理中获取文件名的技术求助

问题:获取SVG集合中文件的文件名作为<symbol>的id属性值

尝试使用XSL-T处理包含大量SVG文件的目录,编写了如下XSL样式表:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
                xmlns="http://www.w3.org/2000/svg"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xpath-default-namespace="http://www.w3.org/2000/svg"
                exclude-result-prefixes="xsl">
  <xsl:output method="xml" doctype-public="-//W3C//DTD SVG 1.1//EN http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"/>
  <xsl:strip-space elements="*"/>

  <xsl:template name="main">
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs/>
      <xsl:apply-templates select="collection(concat(resolve-uri('src/images'),'?select=*.svg;content-type=application/xml'))"/>
    </svg>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates select="svg"/>
  </xsl:template>

  <xsl:template match="svg">
    <xsl:element name="symbol">
      <xsl:attribute name="id"><xsl:value-of select="tokenize(document-uri(/),'/')[last()]"/></xsl:attribute>
      <xsl:attribute name="viewBox"><xsl:value-of select="@viewBox"/></xsl:attribute>
      <xsl:apply-templates select="path"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="path">
    <xsl:element name="path">
      <xsl:apply-templates select="@d,@fill"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@d">
    <xsl:attribute name="d"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

  <xsl:template match="@fill">
    <xsl:attribute name="fill"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

执行转换的命令行:

java net.sf.saxon.Transform -it:main -xsl:"%XSL%\svg-sprite.xsl" -o:"%OUT%\sprite.svg"

目前转换接近成功,但无法获取被导入SVG文件的文件名作为<symbol>的id属性值,尝试过xsl:for-each等方法仍未解决。


解决方案

问题核心是原代码中获取文档URI的上下文未正确指向当前SVG文档,直接遍历集合返回的文档节点即可可靠获取文件名。修改后的XSLT代码如下:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0"
                xmlns="http://www.w3.org/2000/svg"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xpath-default-namespace="http://www.w3.org/2000/svg"
                exclude-result-prefixes="xsl">
  <xsl:output method="xml" doctype-public="-//W3C//DTD SVG 1.1//EN http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"/>
  <xsl:strip-space elements="*"/>

  <xsl:template name="main">
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs/>
      <!-- 遍历集合中的每个SVG文档节点 -->
      <xsl:for-each select="collection(concat(resolve-uri('src/images'),'?select=*.svg;content-type=application/xml'))">
        <!-- 获取当前文档的完整URI -->
        <xsl:variable name="doc-uri" select="document-uri(.)"/>
        <!-- 从URI中提取文件名(去除路径部分) -->
        <xsl:variable name="filename" select="tokenize($doc-uri, '/')[last()]"/>
        <!-- 创建symbol元素,用文件名作为id -->
        <symbol id="{$filename}" viewBox="{svg/@viewBox}">
          <!-- 处理当前文档中的path元素 -->
          <xsl:apply-templates select="svg/path"/>
        </symbol>
      </xsl:for-each>
    </svg>
  </xsl:template>

  <xsl:template match="path">
    <path>
      <xsl:apply-templates select="@d,@fill"/>
    </path>
  </xsl:template>

  <xsl:template match="@d">
    <xsl:attribute name="d"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

  <xsl:template match="@fill">
    <xsl:attribute name="fill"><xsl:value-of select="."/></xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

修改说明:

  1. 移除原有的match="/"和match="svg"模板,改为在main模板中直接用xsl:for-each遍历集合返回的文档节点,确保能直接获取每个文档的URI。
  2. 使用document-uri(.)获取当前文档的完整路径,通过tokenize($doc-uri, '/')[last()]提取最后一段作为文件名。
  3. 用属性值模板简化viewBox的赋值代码,让结构更简洁。

如果需要去掉文件名中的.svg后缀,可将$filename的定义改为:

<xsl:variable name="filename" select="replace(tokenize($doc-uri, '/')[last()], '\.svg$', '')"/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:10:54