2011-06-06 89 views
0

我有以下格式的xml文件。选择两个空节点之间的文本的xsl模板

<root> 
... 

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

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

请建议我选择所有即<start/><end/>标签之间的文本XSL模板。请注意0​​和<end/>是空节点。 非常感谢。

回答

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']" 

然而,这种选择所有节点,而不仅仅是顶级的。 (因此,如果你深复制选定的节点,你会得到副本。)这是因为它是不明确的,如果你有这样的事情应该发生什么样的行为:

<start/> 
<chapter>foo<end/></chapter> 

应该<chapter>选择或不? 但是,如果您可以对开始/结束的相对位置进一步限制,我们可以做得更好。例如。是前<start/>的每一个<end/>兄弟?如果是这样,你可以做

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

+0

如果其中一些假设不正确,请告诉我。 – LarsH 2011-06-06 16:56:45

+0

是的,它应该包含文本和标记。我会试试这个解决方案。非常感谢你。 – Mahesh 2011-06-06 16:58:33

+0

其实标签可能发生在任何级别。 – Mahesh 2011-06-06 17:05:03