2010-08-16 107 views
3

所以這篇文章的標題可能有點誤導,但這是我能想到的最好的。我正在研究一個使用TEI編碼文本的項目。我當前工作的一個要求是編寫XSL轉換以將XML編碼的文本呈現爲HTML。大多數情況下,沒有問題。我有點被困在這個問題上,雖然:帶重疊元素的XSLT?

<l>There is <delSpan spanTo="A1"/>deleted text spanning</l> 
    <l>multiple lines here.<anchor xml:id="A1"/> More text...</l> 

或者,在其他情況下:

<delSpan spanTo="A2"/> 
    <l>Several deleted lines -- the delspan marker can appear </l> 
    <l>outside of an l element.... </l> 
    <anchor xml:id="A2"/> 

(如果你不熟悉的TEI:L =文本行; delSpan =包含多於1行,頁面或更小單元的已刪除文本的範圍。)

目標是顯示delSpan(A1)及其相應錨點(A1)之間的文本 - 「刪除的文本跨越/多行這裏「 - 用一些格式來表示刪除(例如,text-decoration =」line-through「)。現在,有一個用於處理大多數文本格式的「l」元素模板 - 或者至少調用其他模板來完成它。

但這些單身標籤是一個異常;所有其他的格式化/標記都是通過標籤來完成的,這些標籤實際上包含了要格式化的文本。我是否認爲我需要在「l」模板中處理delSpan和錨點元素?處理這個問題並處理僞重疊元素的最優雅方式是什麼?

對不起,如果這是一個noob問題,或者如果我沒有提供足夠的信息。我主要是一個C/C++程序員,只有很少的XSLT經驗,所以我很欣賞任何建議。

回答

2

該樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="delSpan|anchor"/> 
    <xsl:template match="text()[preceding::delSpan[1]/@spanTo=following::anchor[1]/@xml:id]"> 
     <span style="text-decoration:line-through;"> 
      <xsl:value-of select="."/> 
     </span> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<doc> 
    <l>There is <span style="text-decoration:line-through;">deleted text spanning</span></l> 
    <l><span style="text-decoration:line-through;">multiple lines here.</span> More text...</l> 
</doc> 

:使用之前和之後的軸以及它們在文檔順序的意義。我們不會覆蓋任何匹配l元素的previus模板。 delSpananchor也可能未被分條。

+0

從我+1爲好的答案! – 2010-08-16 22:23:17

+0

謝謝!這簡單而優雅,現在對我來說非常有意義。我很享受XSLT的速成課程。 – 2010-08-17 01:54:59

+0

@Andrew Forrester:你好!隨時詢問。 – 2010-08-17 13:06:00

1

您的主要問題在於delSpan元素不是父項,它的結束和關閉「元素」是一個空元素(關閉時爲anchor)。打開和關閉之間的鏈接通過引用xml:id標籤完成。

這個問題有多種解決方案,這裏有一個來自我的頭頂,假設你使用XSLT 1.0(使用XSLT 2.0更容易)。這個想法很簡單:找到所有的兄弟姐妹和應用它們,但前提是他們本身其次是兄弟姐妹anchor用正確xml:id

<xsl:template match="delSpan"> 
    <xsl:variable select="@spanTo" name="spanTo" /> 
    <xsl:apply-templates select="following-sibling::*[following-sibling::anchor[@xml:id = $spanTo]" mode="deleted" /> 
</xsl:template> 

<!-- 
    do this for all elements you need to treat inside delSpan 
    if they have children, remember to use apply-templates with mode deleted 
--> 
<xsl:template match="l" mode="deleted"> 
    <strike><xsl:value-of select="." /></strike> 
</xsl:template> 

我不是100%肯定這是完全正確的。如果<delSpan>可以嵌套,則可能會出錯。如果你幸運的話,Dimitri Novatchev也會走過去看看。