2011-06-06 90 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