我有一系列由Java应用程序输出的文档,这些文档使用未转义的html标记导出XML,例如
<b>some text</b>
(我不能改变这种行为)。
然后使用此输出的应用必须将所有html标记转义为
<b>some text </b>
我使用下面的xslt来转义标签但不出意外它对嵌套 html标签不起作用,例如
<u><b>A string of html</b></u>
在XSLT转换后,我得到了
<u>a string of html</u>
where nested <b> and </b> tags get removed altogether.
我希望实现
<u><b>A string of html</b></u>
我确信通过调整select或模板的值可以轻松回答这个问题,但我已经尝试过并且失败了
非常感谢任何帮助!
带有嵌入式html标签的示例文档
<?xml version="1.0" encoding="UTF-8"?>
<Main>
<Text><u><b>A string of html</b></u></Text>
</Main>
这是XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8"/>
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Text/*">
<xsl:value-of select="concat('<',name(),'>',.,'</',name(),'>')" />
</xsl:template>
</xsl:stylesheet>
哪个产生
<?xml version="1.0" encoding="UTF-8"?>
<Main>
<Text><u>A string of html</u></Text>
</Main>
您可以看到内部粗体标记已被删除。
任何人都可以帮助调整xslt吗?
谢谢: - )
答案 0 :(得分:5)
尝试将当前的Text/*
模板更改为此
<xsl:template match="Text//*">
<xsl:value-of select="concat('<',name(),'>')" />
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
因此,Text//*
将匹配 Text 元素的任何后代元素,而不仅仅是直接子元素。然后分别输出打开和关闭模板,在这些模板之间递归调用模板来处理'嵌套'元素。
当应用于您的示例XML时,应输出以下内容
<Main>
<Text><u><b>A string of html</b></u></Text>
</Main>
答案 1 :(得分:1)
由于您在评论中声明您尝试“转义”的代码可能具有属性,因此Tim C's solution不足。你真正需要的是更像这样的东西(因为你说有问题的标签是HTML我会假设你不需要关心命名空间):
<xsl:template match="Text//*">
<xsl:value-of select="concat('<',name())" />
<xsl:apply-templates select="@*" mode="escape" />
<xsl:text>></xsl:text>
<xsl:apply-templates />
<xsl:value-of select="concat('</',name(),'>')" />
</xsl:template>
<xsl:template match="@*" mode="escape">
<xsl:value-of select="concat(' ', name(), '="')" />
<xsl:call-template name="doubleEscapeQuotes" />
<xsl:text>"</xsl:text>
</xsl:template>
<xsl:template name="doubleEscapeQuotes">
<xsl:param name="value" select="string(.)" />
<xsl:choose>
<xsl:when test="contains($value, '"')">
<xsl:value-of select="substring-before($value, '"')" />
<xsl:text>&quot;</xsl:text>
<xsl:call-template name="doubleEscapeQuotes">
<xsl:with-param name="value" select="substring-after($value, '"')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这会转换
<a title="An "example" website" href="http://example.com">link</a>
到
<a title="An &quot;example&quot; website" href="http://example.com">link</a>
但它仍然缺少一些必要的逻辑 - 你需要在属性值和两个属性值中双重逃避至少&符号(&amp;
)和小于(&lt;
)的符号。 在HTML元素的文本内容中,以便在未转义之后保持生成的标记格式良好(您可能还想逃避大于可读性的标记,但这并不像{{1}那样重要}和&
)。
这比最初出现时要困难得多。 this question的各种答案可能会有所帮助。