如何用XSLT 1.0将XML中指定Run元素转为HTML <mark>标签
问题:XSLT 1.0转换XML到HTML表格时,无法高亮指定Run元素
我正在使用XSLT 1.0将XML文件转换为HTML表格,需要把XML中ExampleText/AStr下namedStyle属性为"Headword in Example"的Run子元素,在HTML输出中用<mark>标签高亮。但当前代码不仅没添加目标<mark>标签,还保留了原XML的Run等标签,达不到预期效果。
输入XML示例片段
<ExampleText> <AStr ws="jii"> <Run ws="jii">Highlighting one piece with fancy style==</Run> <Run namedStyle="Headword in Example" ws="jii">only expected highlighted text</Run> <Run ws="jii">==after highlighted text</Run> </AStr> </ExampleText>
期望HTML输出
Highlighting one piece with fancy style==<mark>only expected highlighted text</mark>==after highlighted text
完整输入XML(test.xml)
<?xml version="1.0" encoding="utf-8"?> <LexExamplePatchSet> <LexExamplePatch> <ExampleText> <AStr ws="jii"> <Run ws="jii">no highlighting</Run> </AStr> </ExampleText> <LexEntText> <AUni ws="jii">Entry One</AUni> </LexEntText> </LexExamplePatch> <LexExamplePatch> <ExampleText> <AStr ws="jii"> <Run ws="jii">highlighting with html mark ==<mark>highlighted text</mark>== unmarked after</Run> </AStr> </ExampleText> <LexEntText> <AUni ws="jii">Entry Two</AUni> </LexEntText> </LexExamplePatch> <LexExamplePatch> <ExampleText> <AStr ws="jii"> <Run ws="jii">Highlighting one piece with fancy style==</Run> <Run namedStyle="Headword in Example" ws="jii">only expected highlighted text</Run> <Run ws="jii">==after highlighted text</Run> </AStr> </ExampleText> <LexEntText> <AUni ws="jii">Entry Three</AUni> </LexEntText> </LexExamplePatch> <LexExamplePatch> <ExampleText> <AStr ws="jii"> <Run ws="jii">Highlighting two pieces with fancy style==</Run> <Run namedStyle="Headword in Example" ws="jii">first expected highlighted text</Run> <Run ws="jii">== between first and second text ==</Run> <Run namedStyle="Headword in Example" ws="jii">second highlighted text</Run> <Run ws="jii">== after the second</Run> </AStr> </ExampleText> <LexEntText> <AUni ws="jii">Entry Four</AUni> </LexEntText> </LexExamplePatch> </LexExamplePatchSet>
原错误XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" exclude-result-prefixes="xs"> <xsl:template match="LexExamplePatchSet"> <html> <head> <title>Example Sentences (with highlighting)</title> </head> <body> <h2>Example Sentences</h2> <table border="1"> <tr bgcolor="#9acd32"> <th>Entry</th> <th>Example Sentence</th> </tr> <xsl:for-each select="LexExamplePatch"> <tr> <td> <xsl:value-of select="LexEntText"/> </td> <td> <xsl:copy-of select="ExampleText"/> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> <xsl:template match="//LexExamplePatch/ExampleText/AStr/Run[@namedStyle='Headword in Example']"> <mark><xsl:value-of select="."/></mark> </xsl:template> <!-- identity transform --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>
问题原因
原代码中使用<xsl:copy-of select="ExampleText"/>直接复制整个ExampleText节点树,不会触发任何模板匹配,包括针对高亮Run的模板。所以原XML标签被保留,高亮逻辑完全没生效。
解决方案:修正XSLT代码
修改代码,替换<xsl:copy-of>为<xsl:apply-templates>,并添加模板处理ExampleText、AStr和普通Run元素,让内容能正确展开并应用高亮逻辑:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" exclude-result-prefixes="xs"> <xsl:template match="LexExamplePatchSet"> <html> <head> <title>Example Sentences (with highlighting)</title> </head> <body> <h2>Example Sentences</h2> <table border="1"> <tr bgcolor="#9acd32"> <th>Entry</th> <th>Example Sentence</th> </tr> <xsl:for-each select="LexExamplePatch"> <tr> <td> <xsl:value-of select="LexEntText"/> </td> <td> <!-- 改为apply-templates触发子节点的模板处理 --> <xsl:apply-templates select="ExampleText"/> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> <!-- 处理ExampleText,只处理其子节点,不保留自身标签 --> <xsl:template match="ExampleText"> <xsl:apply-templates/> </xsl:template> <!-- 处理AStr,只处理其子节点,不保留自身标签 --> <xsl:template match="AStr"> <xsl:apply-templates/> </xsl:template> <!-- 处理普通Run元素,输出文本内容,不保留Run标签 --> <xsl:template match="Run[not(@namedStyle='Headword in Example')]"> <xsl:apply-templates/> </xsl:template> <!-- 处理需要高亮的Run元素,用mark标签包裹内容 --> <xsl:template match="Run[@namedStyle='Headword in Example']"> <mark><xsl:apply-templates/></mark> </xsl:template> <!-- 保留原有的mark标签(如果XML中已存在) --> <xsl:template match="mark"> <xsl:copy> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键修改说明
- 将
<xsl:copy-of select="ExampleText"/>替换为<xsl:apply-templates select="ExampleText"/>,触发针对ExampleText及其子节点的模板匹配,而非直接复制原节点。 - 添加
ExampleText和AStr的模板,仅处理子节点,不保留自身标签,避免原XML结构出现在HTML中。 - 针对普通
Run元素,仅输出其文本内容(包括原有的<mark>标签),不保留Run标签。 - 针对需要高亮的
Run元素,用<mark>标签包裹其内容。 - 添加模板保留原XML中已有的
<mark>标签,确保原有高亮内容不受影响。
测试命令
xsltproc test.xsl test.xml >test-result.html
最终输出效果
生成的HTML会完全符合预期:表格中示例句子列不再有原XML标签,指定的Run元素被<mark>包裹,原XML中的<mark>标签也会保留。
内容的提问来源于stack exchange,提问作者Wes
相关产品推荐
相关产品推荐

