如何让XSLT输出尖括号?生成Markdown中HTML标签技术问询
看来你在XSLT合并XML并输出Markdown时,遇到了一个典型的XML实体转义困境——想要在最终页面里显示<a id="...">这样的标签源码(不被浏览器解析成实际锚点),但直接定义尖括号实体触发了XML结构错误。我来拆解问题并给出可行方案:
为什么你的实体定义会报错?
你尝试定义<![CDATA[<!ENTITY xlab "<" >]]>和<![CDATA[<!ENTITY xrab ">" >]]>,然后在XML里用&xlab;a id="..."&xrab;——这会让XML处理器(Saxon)在解析阶段就把实体替换成真实的<和>,导致你的XML文档出现了未闭合的<a>标签,直接违反了XML“结构必须完整闭合”的规则,所以才会抛出SXXP0003: XML document structures must start and end within the same entity错误。XML根本不允许这种动态生成未闭合元素的操作。
正确的解决方案
你的核心需求是:在最终的Markdown(及转成的HTML)中,显示<a id="...">的文本内容,而不是让它被解析成HTML元素。以下两种方法都能实现:
方法1:直接在XSLT中输出转义字符
放弃自定义实体,直接在XSLT模板里输出<(对应<)和>(对应>)。例如:
<xsl:text><a id="section-1"></xsl:text>
这样生成的Markdown内容就是<a id="section-1">,当转成HTML后,浏览器会自动把<和>渲染成<和>的文字,正好是你要的“仅作为标签定义显示”的效果。
方法2:使用CDATA段批量输出
如果需要输出大量的HTML源码文本,用CDATA段会更方便。XSLT会原样处理CDATA内的内容,配合disable-output-escaping控制转义:
<xsl:text disable-output-escaping="no"><![CDATA[<a id="section-1">]]></xsl:text>
- 这里
disable-output-escaping="no"是默认值,会自动把CDATA里的<>转义成<和>,最终效果和方法1一致; - 如果你偶尔需要让Markdown解析真实的HTML标签(比如实际的锚点),可以把
disable-output-escaping设为yes,这样会直接输出<和>,Markdown处理器会把它当成HTML元素解析。
补充说明
你最开始用&xlt;和&xgt;生成的<a id="...">,其实已经是正确的输出——浏览器打开时显示<a id="...">文字,完全符合你的需求。可能你之前误解了“HTML中直接包含<a...>”的意思,实际上转义后的<和>就是让浏览器显示标签源码的正确方式。
内容的提问来源于stack exchange,提问作者Jonathan Sachs

