XSLT 如何在元素说到时修剪元素前后的空间?

JPM*_*JPM 5 xslt xpath

这个问题出现在格式化使用 TEI 标记的文本文档 (www.tei-c.org) 中。这超出了我的 XSLT/XPATH 技能。(需要 XSLT/XPATH 1.0 中的解决方案。)

有一个标记元素<lb>,用于标记换行符。它可以带有一个属性@break。如果@break="no",则<lb>在生成输出时应忽略文本和周围文本之间的任何空格。

所以

This little tea <lb break="no" />
pot, short and stout.
Run Code Online (Sandbox Code Playgroud)

应该理解为

This little teapot, short and stout.
Run Code Online (Sandbox Code Playgroud)

也就是说,“tea”之后的空格和“pot”之前的换行符不应在输出流中呈现。

对于 之前的空间<lb>,这可以工作:

<xsl:template match="text()[following-sibling::*[1][self::lb[@break='no']]">
    <!-- Do something about the space here. -->
</xsl:template> 
Run Code Online (Sandbox Code Playgroud)

类似的东西也适用于<lb>.

好的。但这更棘手:

This <emph>little <ref>tea </ref> </emph>
<lb break="no" />
pot, short and stout.
Run Code Online (Sandbox Code Playgroud)

现在<ref>元素内的文本不是<lb>. 并且需要从输出流中删除</ref>之前的空间、之前的空间</emph>和前后的换行符<lb>

如何?

Tom*_*man 1

尝试使用如下选择器:

text()[matches(., '\S?\s*$') and not following::text()[matches('\S')] and following::lb[@break="no"]]
Run Code Online (Sandbox Code Playgroud)

当然,这是可怕且低效的。但可能有效。不会工作,因为正如已经指出的,你没有 matches()。我会再去一次:

好的,我们正在寻找四种不同的场景:

  • 第一个前面的非空文本元素(如果它以空格结尾):

    lb[@break='no']/preceding::text()[normalize-space()!='' 和 string-length(substring-after(.,normalize-space()))!=0][1 ]

  • 第一个前面的非空文本元素后面的空文本元素:

    lb[@break='no']/前面的::text()[normalize-space()='' 和前面的::text()[normalize-space()!='']]

  • 第一个非空文本元素之前的空文本元素:

    lb[@break='no']/following::text()[normalize-space()!='' 和 string-length(substring-before(.,normalize-space()))!=0][1 ]

  • 第一个以下非空文本元素(如果它以空格开头):

    lb[@break='no']/以下::text()[normalize-space()='' 和以下::text()[normalize-space()!='']]

因为您无法在 xpath 1.0 中使用 union,所以您必须使用此方法从上述每个匹配中调用模板。