如何使用XSLT更改标记位置,但不提及元素名称。即我们不知道该元素应该是<br/>
标记的父元素。
示例:如果<br/>
标记为任何元素的第一个子节点,但不是<p>
或<td>
。此案例<br/>
标记应放在元素之外。在这里,我给出了输入和所需的输出:
输入:
<p>Test <b><i><br/>case</i></b></p>
必需输出:
<p>Test <br/><b><i>case</i></b></p>
答案 0 :(得分:1)
从身份转换开始。为模板提供名称(例如idt-elem
)。
添加与第一个孩子为br
的任何元素匹配的模板。如果您的输入是XHTML,并且您已将前缀xh
绑定到XHTML命名空间,则此模板的可能匹配模式为*[child::node()[1]/self::xh:br]
。在该模板中,首先发出br
元素,然后调用模板idt-elem
。
如果这应该仅匹配p
和td
以外的元素,则为这两个元素添加更高优先级,调用idt-elem
。
为br
元素添加模板,这些元素是除p
和td
以外的任何元素的第一个子元素。让它什么都不做。
生成的样式表会将初始br
元素移出父母,并立即让他们的父母留下兄弟姐妹。要处理像<b><i><br/>...</i></b>
这样的情况,您需要运行两次样式表。通常,运行它直到其输出不再与其输入不同。 (或者为根节点添加模板,测试是否要移动任何br
元素,否则发出消息。)
答案 1 :(得分:0)
我们了解到,您需要将<br>
作为第一个孩子移动,而不需要在树上添加文本到<p>
或<td>
级别。我已经扩展了示例以涵盖更多可能的案例:
<test>
<!-- these cases are ok -->
<p>Test <br/>case</p>
<p>Test <br/><b>case</b></p>
<p>Test <br/><i>case</i></p>
<p>Test <i>case<br/></i></p>
<p>Test <b><i>case</i><br/></b></p>
<p>Test <b><i>case<br/>case<br/></i></b></p>
<!-- here should happen something -->
<p>Test <b><br/>case</b></p>
<p>Test <b><i><br/>case</i></b></p>
<p>Test <i><br/><b>case</b></i></p>
<!-- mixed case -->
<p>Test <i><b><br/>case<br/></b></i></p>
<!-- edit: additional example -->
<p><br/><x>0.03-</x></p>
</test>
现在,替换过程需要组件:首先,删除位于错误位置的所有br
,然后,在所需位置创建它们的副本。以这种方式识别相关的br
:如果前兄弟或其后代是文本节点,则br
需要保持原样。在其他情况下,它可以在树上复制。就是这样。可以通过身份模板复制所有其他元素。
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="p/*
[descendant::br
[not(preceding-sibling::node()
/descendant-or-self::text())]]">
<xsl:copy-of select="descendant::br
[not(preceding-sibling::node()
/descendant-or-self::text())]"/>
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!--<xsl:template match="p//br
[not(preceding-sibling::node()/descendant-or-self::text())]"/>-->
<!-- edit: fixed version -->
<xsl:template match="p/*//br
[not(preceding-sibling::node()
/descendant-or-self::text())]"/>
这应该产生以下结果:
<test>
<!-- these cases are ok -->
<p>Test <br/>case</p>
<p>Test <br/><b>case</b></p>
<p>Test <br/><i>case</i></p>
<p>Test <i>case<br/></i></p>
<p>Test <b><i>case</i><br/></b></p>
<p>Test <b><i>case<br/>case<br/></i></b></p>
<!-- here should happen something -->
<p>Test <br/><b>case</b></p>
<p>Test <br/><b><i>case</i></b></p>
<p>Test <br/><i><b>case</b></i></p>
<!-- mixed case -->
<p>Test <br/><i><b>case<br/></b></i></p>
<!-- edit: additional example -->
<p><br/><x>0.03-</x></p>
</test>