我正在尝试清理我提供的一批XML。我需要考虑三种情况:
- 某些元素中包含纯文本,例如。
<item>some text</item>
,需要包装在另一个标签中,例如。<item><p>some text</p></item>
- 某些元素在其中转义了 XML,例如。
<item><p>some text</p></item>
,需要在不转义的情况下输出:<item><p>some text</p></item>
- 一些元素已经转义了需要包装的XML,例如。
<item>some <em>text</em></item>
需要变得<item><p>some <em>text</em></p></item>
<item>
在这两种情况下都用作容器。
我可以相对容易地满足条件 1,我可以用 disable-output-escaping
满足条件 2,但我不能用这种方法满足条件 3。
我想如果我能测试<item>
中的文本是否被转义,我可以满足 2(可能 3(,但使用 contains(., '&lt;')
的测试不匹配。 所以...
如何测试节点中的文本是否为转义 XML?
- 和 3. 两者都需要在 1. 中包装和禁用输出转义。 不会有什么坏处,所以我认为你可以用同一个模板将它们一起处理。
我没有看到明确的检查元素内容是否包含具有纯 XSLT 1.0 手段的转义元素标记,所以我只是尝试了
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[not(*) and not(starts-with(., '<') and substring(., string-length(.)) = '>')]">
<xsl:copy>
<p>
<xsl:value-of select="." disable-output-escaping="yes"/>
</p>
</xsl:copy>
</xsl:template>
<xsl:template match="item[not(*)
and starts-with(., '<') and substring(., string-length(.)) = '>']">
<xsl:copy>
<xsl:value-of select="." disable-output-escaping="yes"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
哪个转换
<root>
<item>some text</item>
<item><p>some text</p></item>
<item>some <em>text</em></item>
</root>
到
<html><body>
<item><p>some text</p></item>
<item><p>some text</p></item>
<item><p>some <em>text</em></p></item>
</body></html>
显然,它也会<item><...></item>
变成<item><...></item>
。您可以尝试实现更多的字符串检查,但如果没有转义 XML 片段的完整解析器,始终可以在字符串检查失败的情况下构造输入样本。