我有以下格式的xml文件。
<root>
...
<start/>
some text <b> bold </b>
<end/>
...
<start/>
some other text <i>italic </i>
<end/>
...
</root>
请为我推荐一个xsl模板,用于选择<start/>
和<end/>
代码之间的所有文字。请注意<start/>
和<end/>
是空节点。
非常感谢你。
答案 0 :(得分:3)
我正在解释您的“所有文字”,不仅包括文字节点本身,还包括<b>
等标记。我还假设您不希望选择<start/>
和<end/>
之间的每个后代节点,而只选择顶级节点。此外,我假设所有<start/>
和<end/>
标签都是兄弟(不能在任何级别出现)。
使用以下模板选择(并复制)<start/>
和<end/>
代码之间的所有文字。
<xsl:template match="/">
<xsl:copy-of select="(//start)[1]/following-sibling::node()[not(self::end) and
name((preceding-sibling::start | preceding-sibling::end)[last()]) = 'start']"/>
</xsl:template>
<强>更新强>
鉴于您的开始/结束可以处于任何级别,您可以从上面的轴中删除-sibling
:
select="(//start)[1]/following::node()[not(self::end) and
name((preceding::start | preceding::end)[last()]) = 'start']"
但是,这会选择 all 节点,而不仅仅是顶级节点。 (因此,如果您对所选节点进行深层复制,您将获得重复项。)这是因为如果您有类似这样的事情,那么行为应该发生的事情没有明确定义:
<start/>
<chapter>foo<end/></chapter>
是否应该选择<chapter>
?
但是,如果您可以对开始/结束相对于彼此的位置进行进一步限制,我们可以做得更好。例如。每个<end/>
是前一个<start/>
的兄弟姐妹吗?如果是这样,你可以做
<xsl:key name="text-by-last-milestone" match="* | text()"
use="generate-id((preceding-sibling::start | preceding-sibling::end)[last()])" />
<xsl:template match="/">
<xsl:for-each select="//start">
<xsl:copy-of select="key('text-by-last-milestone', generate-id())"/>
</xsl:for-each>
</xsl:template>
如果没有,那么显示更多扩展的输入样本对您有所帮助。
仅供参考,这些标签被称为“里程碑”标记,因此您可以通过搜索该术语来查找有关处理它们的更多信息。根据输入XML的约束条件,它们也被称为“并发标记”。