如何在终止XSLT 2.0处理前打印所有缺失@appname属性的实例
修改XSLT模板以输出所有缺失@appname的Topic后再终止处理
问题背景
开发DITA-OT插件时,现有XSLT模板检测到topic元素缺失@appname属性时,会在遇到第一个缺失实例时立即终止处理,无法在日志中查看所有缺失情况。需要修改模板,先打印所有缺失实例,再终止XSLT处理。
修改思路
- 先遍历所有目标topicref节点,输出所有缺失
@appname的错误信息(不立即终止) - 完成所有错误收集后,判断是否存在错误实例,若存在则终止处理
修改后的完整XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 全局变量:存储所有缺失appname的topic错误信息 --> <xsl:variable name="missingAppnameErrors"> <xsl:apply-templates select="//*[contains(@class, ' map/topicref ')][not(@toc = 'no')][not(@processing-role = 'resource-only')]" mode="check-appname"/> </xsl:variable> <!-- 根模板:先执行全量检查,再决定是否终止 --> <xsl:template match="/"> <!-- 输出所有缺失appname的错误日志 --> <xsl:copy-of select="$missingAppnameErrors"/> <!-- 若存在错误,终止处理流程 --> <xsl:if test="$missingAppnameErrors/error"> <xsl:message terminate="yes"> 检测到以上Topic缺失@appname属性,处理终止。 </xsl:message> </xsl:if> <!-- 继续原有正常处理流程 --> <xsl:apply-templates/> </xsl:template> <!-- 原有匹配模板:移除即时终止逻辑,保留原处理流程 --> <xsl:template match="*[contains(@class, ' map/topicref ')][not(@toc = 'no')][not(@processing-role = 'resource-only')]"> <xsl:variable name="WORKDIR" select="'/work/'"/> <xsl:variable name="FileWithPath"> <xsl:value-of select="$WORKDIR"/> <xsl:value-of select="substring-before(@href, '#')"/> </xsl:variable> <xsl:variable name="TargetFile" select="document($FileWithPath, /)"/> <xsl:choose> <xsl:when test="contains(@class, ' mapgroup/topicgroup ')"> <xsl:apply-templates/> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="*[contains(@class, ' map/topicref mapgroup-d/topichead ')] or contains(@class, ' map/topicref mapgroup-d/topichead ')"> <xsl:apply-templates/> </xsl:when> <xsl:otherwise> <topic> <xsl:apply-templates/> </topic> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 专用检查模板:遍历所有节点收集缺失appname的错误 --> <xsl:template match="*[contains(@class, ' map/topicref ')][not(@toc = 'no')][not(@processing-role = 'resource-only')]" mode="check-appname"> <xsl:variable name="WORKDIR" select="'/work/'"/> <xsl:variable name="FileWithPath"> <xsl:value-of select="$WORKDIR"/> <xsl:value-of select="substring-before(@href, '#')"/> </xsl:variable> <xsl:variable name="TargetFile" select="document($FileWithPath, /)"/> <!-- 跳过不需要检查的节点类型 --> <xsl:if test="not(contains(@class, ' mapgroup/topicgroup ')) and not(*[contains(@class, ' map/topicref mapgroup-d/topichead ')]) and not(contains(@class, ' map/topicref mapgroup-d/topichead '))"> <xsl:if test="not($TargetFile/*[contains(@class, ' topic/topic ')]/*[contains(@class, ' topic/prolog ')]/*[contains(@class, ' topic/resourceid ')][@appname = 'abc'])"> <error> <xsl:message> Error: Topic does not contain appname 'abc' - ID: <xsl:value-of select="$TargetFile/*[contains(@class, ' topic/topic ')]/@id"/> </xsl:message> </error> </xsl:if> </xsl:if> <!-- 递归检查子节点 --> <xsl:apply-templates mode="check-appname"/> </xsl:template> </xsl:stylesheet>
关键修改说明
- 新增全局变量
$missingAppnameErrors:通过check-appname专用模式遍历所有目标节点,收集所有缺失@appname的错误信息 - 新增根模板:先输出所有错误日志,再判断是否存在错误,若存在则终止处理
- 原有匹配模板移除即时终止逻辑:不再遇到错误就立即停止,保证所有节点都能被检查
- 新增**
check-appname模式模板**:专门负责检查@appname缺失情况,递归处理子节点,确保所有符合条件的topicref都被覆盖检查
内容的提问来源于stack exchange,提问作者user19732805
相关产品推荐
相关产品推荐

