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>
修改说明:
- 移除原有的
match="/"和match="svg"模板,改为在main模板中直接用xsl:for-each遍历集合返回的文档节点,确保能直接获取每个文档的URI。 - 使用
document-uri(.)获取当前文档的完整路径,通过tokenize($doc-uri, '/')[last()]提取最后一段作为文件名。 - 用属性值模板简化
viewBox的赋值代码,让结构更简洁。
如果需要去掉文件名中的.svg后缀,可将$filename的定义改为:
<xsl:variable name="filename" select="replace(tokenize($doc-uri, '/')[last()], '\.svg$', '')"/>
内容的提问来源于stack exchange,提问作者TheChrisPratt
相关产品推荐
相关产品推荐

