这是此处发布的其他问题的略微版本: XSLT: change node inner text
想象一下,我使用XSLT来转换文档:
<a>
<b/>
<c/>
</a>
进入这个:
<a>
<b/>
<c/>
Hello world
</a>
在这种情况下我不能同时使用
<xsl:strip-space elements="*"/>
元素或[normalize-space()!='']谓词,因为我需要放置新文本的地方没有文字。有任何想法吗?感谢。
答案 0 :(得分:2)
此转换在名为a7
的元素之后插入所需的文本(一般性):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a7">
<xsl:call-template name="identity"/>
<xsl:text>Hello world</xsl:text>
</xsl:template>
</xsl:stylesheet>
应用于此XML文档时:
<a>
<a1/>
<a2/>
.....
<a7/>
<a8/>
</a>
产生了所需的结果:
<a>
<a1/>
<a2/>
.....
<a7/>Hello world
<a8/>
</a>
请注意:
使用identity rule复制源XML文档的每个节点。
通过执行新文本插入的特定模板覆盖身份规则。
身份规则如何应用(在每个节点上)并按名称调用(针对特定需求)。
答案 1 :(得分:2)
以下是我要做的事情:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- identity template to copy everything unless otherwise noted -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- match the first text node directly following a <c> element -->
<xsl:template match="text()[preceding-sibling::node()[1][self::c]]">
<!-- ...and change its contents -->
<xsl:text>Hello world</xsl:text>
</xsl:template>
</xsl:stylesheet>
请注意,文本节点包含“周围”空格 - 在问题的示例XML中,匹配的文本节点仅为空白,这就是上述工作的原因。一旦输入文档如下所示,它将停止工作:
<a><b/><c/></a>
因为<c>
后面没有文本节点。因此,如果这对您的用例来说太脆弱,那么另一种选择是:
<!-- <c> nodes get a new adjacent text node -->
<xsl:template match="c">
<xsl:copy-of select="." />
<xsl:text>Hello world</xsl:text>
</xsl:template>
<!-- make sure to remove the first text node directly following a <c> node-->
<xsl:template match="text()[preceding-sibling::node()[1][self::c]]" />
在任何情况下,像上面这样的东西都清楚地说明了为什么最好避免文本节点和元素节点的混合。这并不总是可行的(参见XHTML)。但是当你有机会并且XML应该纯粹是结构数据的容器时,保持清晰的混合内容会让你的生活更轻松。
答案 2 :(得分:0)
编辑:修复我无法在其中输入正确的语法。
<xsl:template match='a'>
<xsl:copy-of select="." />
<xsl:text>Hello World</xsl:text>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>