如何用XSLT 3.0修正Access RTF转XML的嵌套列表格式问题
解决方案:修复Access导出XML中的嵌套列表层级问题
1. 剥离Access自动生成的冗余容器
Access会给自定义标记套上<div>和<font>节点,第一步先把这些冗余容器剥离,只保留有效内容和标记:
<!-- 直接跳过<div>容器,处理其子节点 --> <xsl:template match="div"> <xsl:apply-templates select="node()"/> </xsl:template> <!-- 处理非标记类的<font>节点,直接输出文本 --> <xsl:template match="font[not(contains(text(), '<list2>') or contains(text(), '<list3>'))]"> <xsl:value-of select="normalize-space(text())"/> </xsl:template>
2. 用XSLT 3.0分组构建嵌套列表
利用xsl:for-each-group的group-starting-with特性,按自定义标记为分组起点,递归构建嵌套列表结构:
<!-- 匹配存储列表内容的父节点(替换为你实际的容器节点名) --> <xsl:template match="rtf-content"> <list level="1"> <!-- 按二级标记分组,处理一级和二级列表 --> <xsl:for-each-group select="node()" group-starting-with="font[contains(text(), '<list2>')]"> <xsl:choose> <!-- 处理一级列表项 --> <xsl:when test="not(current-grouping-key())"> <list-item level="1"> <xsl:apply-templates select="current-group()"/> </list-item> </xsl:when> <!-- 处理二级列表项,嵌套到上一级列表中 --> <xsl:when test="contains(current-grouping-key()/text(), '<list2>')"> <list-item level="1"> <list level="2"> <!-- 再按三级标记分组,处理二级和三级列表 --> <xsl:for-each-group select="current-group()" group-starting-with="font[contains(text(), '<list3>')]"> <xsl:choose> <xsl:when test="not(current-grouping-key())"> <list-item level="2"> <xsl:apply-templates select="current-group()[not(self::font[contains(text(), '<list2>')])]"/> </list-item> </xsl:when> <xsl:when test="contains(current-grouping-key()/text(), '<list3>')"> <list-item level="2"> <list level="3"> <list-item level="3"> <xsl:apply-templates select="current-group()[not(self::font[contains(text(), '<list3>')])]"/> </list-item> </list> </list-item> </xsl:choose> </xsl:for-each-group> </list> </list-item> </xsl:when> </xsl:choose> </xsl:for-each-group> </list> </xsl:template>
XSLT代码优化建议
- 统一管理标记变量:把层级标记定义为变量,避免硬编码,方便后续扩展或修改:
<xsl:variable name="level2-mark" select="'<list2>'"/> <xsl:variable name="level3-mark" select="'<list3>'"/> - 递归处理层级:如果后续需要支持更多层级,用递归模板代替硬编码二级/三级逻辑,提升扩展性:
<xsl:template name="build-nested-list"> <xsl:param name="current-level" select="1"/> <xsl:param name="nodes"/> <list level="{$current-level}"> <xsl:for-each-group select="$nodes" group-starting-with="font[contains(text(), concat('<list', $current-level + 1, '>'))]"> <list-item level="{$current-level}"> <xsl:if test="current-grouping-key()"> <xsl:call-template name="build-nested-list"> <xsl:with-param name="current-level" select="$current-level + 1"/> <xsl:with-param name="nodes" select="current-group()"/> </xsl:call-template> </xsl:if> <xsl:apply-templates select="current-group()[not(self::font[contains(text(), concat('<list', $current-level + 1, '>'))])]"/> </list-item> </xsl:for-each-group> </list> </xsl:template> - 清理冗余空白:对所有文本节点应用
normalize-space(),避免Access导出时带的多余空格影响格式。
内容的提问来源于stack exchange,提问作者DSB
相关产品推荐
相关产品推荐

