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

如何修改XSL-FO代码以适配任意@*标记组合?

问题:适配任意@*标记的XSL-FO文本转换

此前我提问《Convert text string to xml tagging using xsl pt.2》并获得解决方案,据此编写了XSL-FO代码。需求是将含@c、@v标记的XML文本(如<p>The @c cmdname is a utility and @v varname is an option.</p>)转换为对应格式:cmdname使用等宽字体,varname使用斜体。但当前代码仅@c标记生效,且无法直接使用<i>等XML标签。

现有XSL-FO代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="2.0">

<xsl:template match="text()[contains(., '@c')]">
   <xsl:analyze-string select="." regex="@c\s+([!-~]+)">
      <xsl:matching-substring>
         <fo:inline font-family="RobotoMono-Regular">
            <xsl:value-of select="regex-group(1)"/>
         </fo:inline>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
         <xsl:value-of select="."/>
      </xsl:non-matching-substring>
   </xsl:analyze-string>
</xsl:template>

<xsl:template match="text()[contains(., '@v')]">
   <xsl:analyze-string select="." regex="@v\s+([!-~]+)">
      <xsl:matching-substring>
         <fo:inline font-family="Roboto" font-style="italic">
            <xsl:value-of select="regex-group(1)"/>
         </fo:inline>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
         <xsl:value-of select="."/>
      </xsl:non-matching-substring>
   </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

解决方案

问题根源

当前两个模板是互斥的:一个文本节点只会匹配第一个符合条件的模板(比如同时包含@c和@v的文本,只会触发@c的模板,@v的标记不会被处理)。要适配任意@*标记,需要合并处理逻辑,用单一正则匹配所有@开头的标记,再根据标记类型应用对应样式。

修改后的代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                version="2.0">

<!-- 匹配所有文本节点,统一处理所有@*标记 -->
<xsl:template match="text()">
   <xsl:analyze-string select="." regex="@([cv])\s+([!-~]+)">
      <xsl:matching-substring>
         <!-- 根据捕获的标记类型选择对应FO样式 -->
         <xsl:choose>
            <!-- @c标记:等宽字体 -->
            <xsl:when test="regex-group(1) = 'c'">
               <fo:inline font-family="RobotoMono-Regular">
                  <xsl:value-of select="regex-group(2)"/>
               </fo:inline>
            </xsl:when>
            <!-- @v标记:斜体 -->
            <xsl:when test="regex-group(1) = 'v'">
               <fo:inline font-family="Roboto" font-style="italic">
                  <xsl:value-of select="regex-group(2)"/>
               </fo:inline>
            </xsl:when>
            <!-- 可扩展:新增其他@*标记的样式分支 -->
            <!-- <xsl:when test="regex-group(1) = 'b'">
               <fo:inline font-weight="bold">
                  <xsl:value-of select="regex-group(2)"/>
               </fo:inline>
            </xsl:when> -->
         </xsl:choose>
      </xsl:matching-substring>
      <xsl:non-matching-substring>
         <xsl:value-of select="."/>
      </xsl:non-matching-substring>
   </xsl:analyze-string>
</xsl:template>

</xsl:stylesheet>

关键说明

  1. 合并模板:用单个模板匹配所有文本节点,避免互斥问题,确保所有@*标记都能被处理
  2. 通用正则:@([cv])\s+([!-~]+) 捕获两部分内容:([cv])是标记类型(可扩展为([cvb])等),([!-~]+)是标记后的目标文本
  3. 动态样式:通过xsl:choose根据标记类型切换FO样式,后续新增标记只需添加对应的xsl:when分支
  4. 命名空间修复:补充了FO的命名空间声明(xmlns:fo="http://www.w3.org/1999/XSL/Format"),否则<fo:inline>标签无法生效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 05:37:10