xsl模板,用于选择两个空节点之间的文本

时间:2011-06-06 16:36:23

标签: xml xslt

我有以下格式的xml文件。

<root>
...

<start/>
 some text <b> bold </b>
<end/>
...

<start/>
 some other text <i>italic </i>
<end/>
...
</root>

请为我推荐一个xsl模板,用于选择<start/><end/>代码之间的所有文字。请注意<start/><end/>是空节点。 非常感谢你。

1 个答案:

答案 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的约束条件,它们也被称为“并发标记”。