【问题标题】:XSLT with overlapping elements?具有重叠元素的 XSLT?
【发布时间】:2010-08-17 03:47:17
【问题描述】:

所以这篇文章的标题可能有点误导,但这是我能想到的最好的。我正在开发一个使用 TEI 对文本进行编码的项目。我当前工作的要求之一是编写 XSL 转换以将 XML 编码的文本呈现为 HTML。在大多数情况下,没有问题。不过,我有点卡在这个问题上:

    <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= “直通”)。现在,有一个用于处理大多数文本格式的“l”元素模板——或者至少调用其他模板来完成它。

但是这些单例标签是异常的;所有其他格式化/标记都是通过实际包含它们要格式化的文本的标签来完成的。我是否正确假设我需要处理“l”模板中的 delSpan 和锚元素?解决这个问题和处理伪重叠元素的最优雅的方法是什么?

对不起,如果这是一个菜鸟问题,或者我没有提供足够的信息。我主要是一名 C/C++ 程序员,几乎没有 XSLT 经验,所以我很感激任何建议。

【问题讨论】:

    标签: xml xslt xpath


    【解决方案1】:

    这个样式表:

    <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 也不能被条带化。

    【讨论】:

    • 谢谢!这简单而优雅,现在对我来说非常有意义。我正在享受 XSLT 速成课程。
    • @Andrew Forrester:你很高兴!随时询问。
    【解决方案2】:

    您的主要问题是 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% 确定这是完全正确的。如果&lt;delSpan&gt; 可以嵌套,可能会出错。如果幸运的话,Dimitri Novatchev 也会走过来看看。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      相关资源
      最近更新 更多